CF671E Organizing a Race
原发布于2020-01-14。
upd 2020-04-10: 代码写错了,被hack了,已更正
网上大多数都是
题解
首先考虑没有
将题意中的
设
那么
那么考虑有
如果
从
那么为了
接下来考虑
设
显然剩下的
如果对于
可以在单调栈二分出
时间复杂度
代码
已define int long long
int a[100005],b[100005],f[100005],g[100005];
int s[100005],t;
int n,k;
struct smt{
int amn,bmn,atg;
int ls,rs;
smt *l,*r;
smt(int la,int ra){
amn=inf;bmn=-inf;
atg=0;
ls=la;rs=ra;
if(ls==rs){
l=r=0;
}
else{
int mid=(ls+rs)>>1;
l=new smt(ls,mid);
r=new smt(mid+1,rs);
}
}
void setg(int x){
if(ls==rs){
amn=bmn=g[x];
return;
}
if(x<=l->rs)l->setg(x);
else r->setg(x);
amn=min(l->amn,r->amn);
bmn=min(l->bmn,r->bmn);
}
void push_down(){
l->atg+=atg;
l->amn+=atg;
r->atg+=atg;
r->amn+=atg;
atg=0;
}
void add(int la,int ra,int w){
if(la<=ls && rs<=ra){
atg+=w;amn+=w;
return;
}
push_down();
if(la<=l->rs)l->add(la,ra,w);
if(ra>=r->ls)r->add(la,ra,w);
amn=min(l->amn,r->amn);
}
int query(int x,int rm){
if(ls>rm)return 0;
if(bmn-k>x)return 0;//没加这一句话会错
if(ls==rs)return ls;
push_down();
if(min(x,l->amn)>=r->bmn-k){
int ans=r->query(min(x,l->amn),rm);
if(ans)return ans;
}
return l->query(x,rm);
}
};
smt *rt;
signed main(){
#ifdef QAQAutoMaton
freopen("E.in","r",stdin);
freopen("E.out","w",stdout);
#endif
read(n,k);
rt=new smt(1,n);
for(int i=1;i<n;++i)read(b[i]);
for(int i=1;i<=n;++i)read(a[i]);
for(int i=1;i<=n;++i){
f[i]=f[i-1]+a[i-1]-b[i-1];
}
for(int i=1;i<=n;++i){
g[i]=g[i-1]+b[i-1]-a[i];
}
int ans=0;
for(int i=n;i;--i){
rt->setg(i);
while(t && f[s[t]]>=f[i]){
if(t>1){
rt->add(s[t-1]-1,n,f[s[t]]-f[s[t-1]]);
}
--t;
}
s[++t]=i;
if(t>1){
rt->add(s[t-1]-1,n,f[s[t-1]]-f[s[t]]);
}
s[0]=n+1;
int l=1,r=t,mid;
while(l<=r){
mid=(l+r)>>1;
if(f[i]-f[s[mid]]<=k)r=mid-1;
else l=mid+1;
}
chkmax(ans,rt->query(inf,s[r]-1)-i+1);
}
write(ans,'\n');
return 0;
}