题解:CF2089B1 Canteen (Easy Version)
赛时做了很一会。
我们考虑我们不是转
对于一个位置
如果
否则我们考虑转的
如果是时刻
然后求所有这样的
此处的转化容易证明,这里不过多赘述。
我们有个显然的套路就是断环成长度两倍的链,自然做就行。
我们让每个
每个
我们可以实时线段树维护对于每个
可是我们代码能力太弱了,又懒,怎么办呢?
发现转化后还有个点没用到就是我们求最大值就行。
所以我们可以维护此时的最大值。
考虑以
如果大于
然而,如果答案不变,我们就麻烦了。
当
猛地,我们想到单调队列。
于是每次就是
然后前缀和都加上一个数,计懒标记即可。
然后加入自己。
然后如果队头大于
这里的代码把数组翻转,方便思考,所以维护后缀和。
#include<bits/stdc++.h>
#define int long long
#define pii pair<int,int>
#define F first
#define S second
using namespace std;
int a[1000009];
pii q[1000009];
int h=300000,t=299999;
void _main(){
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
int b;
cin>>b;
a[i]-=b;
}
for(int i=n+1;i<=n+n;i++){
a[i]=a[i-n];
}
h=300000,t=299999;
q[h]={0,-1e16};
n*=2;
for(int i=1;i<=n/2;i++){
swap(a[i],a[n-i+1]);
}
int qq;
qq=0;
int ma;
ma=1;
int hz;
hz=-1e18;
a[0]=-1e18;
for(int i=1;i<=n;i++){
hz-=a[i-ma];
hz+=a[i];
if(h<=t){
if(q[h].F<=i-ma){
++h;
}
}
int aa;
aa=a[i];
qq+=aa;
aa-=qq;
while(h<=t&&aa<=q[t].S){
t--;
}
q[++t]={i,aa};
while(q[h].S+qq>0){
hz+=a[i-ma];
ma++;
if(hz-qq<q[h].S){
q[--h]={i-ma,hz-qq};
}
}
}
cout<<ma<<endl;
}
signed main(){
int t;
cin>>t;
while(t--){
_main();
}
return 0;
}