[BJOI2017]开车
直接做要用栈
修改?难以直接维护
统计边的贡献!
len*abs(pre)pre表示前缀car-stop
修改时候,整个区间的pre+1或者-1
分块,块内对pre排序并打标记
二分出0的位置,再根据pre的正负和本次是+1,-1,leni贡献+1还是-1的贡献
O(nsqrt(n)logn)
#include<bits/stdc++.h> #define reg register int #define il inline #define fi first #define se second #define mk(a,b) make_pair(a,b) #define numb (ch^'0') using namespace std; typedef long long ll; template<class T>il void rd(T &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');} template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');} template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');} namespace Miracle{ const int N=3*5e4+5; const int B=450; int n,m; int L[N],R[N]; struct qs{ int id,x; }q[N]; int c[N],cnt; int tot; int pos[N],b[N]; int be[N],len[N]; vector<int>mem[B],sum[B]; int tag[B]; ll con[B]; int exi[N];//0: none 1:car -1:stop int pre[N]; int buc[N]; bool cmp(int x,int y){ return pre[x]<pre[y]; } int li(int x){ return lower_bound(c+1,c+cnt+1,x)-c; } int main(){ rd(n); for(reg i=1;i<=n;++i) rd(pos[i]),c[++cnt]=pos[i]; for(reg i=1;i<=n;++i) rd(b[i]),c[++cnt]=b[i]; rd(m); for(reg i=1;i<=m;++i){ rd(q[i].id);rd(q[i].x); c[++cnt]=q[i].x; } sort(c+1,c+cnt+1); cnt=unique(c+1,c+cnt+1)-c-1; int blo=sqrt(cnt)+1; for(reg i=1;i<=cnt;++i){ be[i]=(i-1)/blo+1; if(!L[be[i]]) L[be[i]]=i; R[be[i]]=i; len[i]=c[i+1]-c[i]; } len[cnt]=0; tot=be[cnt]; for(reg i=1;i<=n;++i){ int po=lower_bound(c+1,c+cnt+1,b[i])-c; --exi[po]; po=lower_bound(c+1,c+cnt+1,pos[i])-c; ++exi[po]; } ll ans=0; for(reg i=1;i<=cnt;++i){ pre[i]=pre[i-1]+exi[i]; ans+=(ll)len[i]*abs(pre[i]); } for(reg j=1;j<=tot;++j){ tag[j]=0; for(reg i=L[j];i<=R[j];++i){ mem[j].push_back(i); con[j]+=(ll)len[i]*abs(pre[i]); } sort(mem[j].begin(),mem[j].end(),cmp); sum[j].resize(mem[j].size()); for(reg i=0;i<(int)mem[j].size();++i){ sum[j][i]=len[mem[j][i]]; if(i) sum[j][i]+=sum[j][i-1]; } } printf("%lld\n",ans); for(reg o=1;o<=m;++o){ int l=li(pos[q[o].id]),r=li(q[o].x); exi[l]--;exi[r]++; int c=-1;//l->r if(l>r) swap(l,r),c=1;//r->l --r;//warinig!!! if(be[l]==be[r]){ for(reg i=l;i<=r;++i) pre[i]+=c; ans-=con[be[l]]; con[be[l]]=0; mem[be[l]].clear(); sum[be[l]].clear(); int j=be[l]; for(reg i=L[be[l]];i<=R[be[l]];++i){ pre[i]+=tag[be[l]]; mem[j].push_back(i); } sort(mem[j].begin(),mem[j].end(),cmp); sum[j].resize(mem[j].size()); for(reg i=0;i<(int)mem[j].size();++i){ sum[j][i]=len[mem[j][i]]; con[j]+=(ll)len[mem[j][i]]*abs(pre[mem[j][i]]); if(i) sum[j][i]+=sum[j][i-1]; } tag[be[l]]=0; ans+=con[be[l]]; }else{ for(reg i=l;i<=R[be[l]];++i){ pre[i]+=c; } int j=be[l]; ans-=con[j]; con[j]=0; mem[j].clear(); sum[j].clear(); for(reg i=L[j];i<=R[j];++i){ pre[i]+=tag[j]; mem[j].push_back(i); } sort(mem[j].begin(),mem[j].end(),cmp); sum[j].resize(mem[j].size()); for(reg i=0;i<(int)mem[j].size();++i){ sum[j][i]=len[mem[j][i]]; con[j]+=(ll)len[mem[j][i]]*abs(pre[mem[j][i]]); if(i) sum[j][i]+=sum[j][i-1]; } tag[j]=0; ans+=con[j]; for(reg i=L[be[r]];i<=r;++i){ pre[i]+=c; } j=be[r]; ans-=con[j]; con[j]=0; mem[j].clear(); sum[j].clear(); for(reg i=L[j];i<=R[j];++i){ pre[i]+=tag[j]; mem[j].push_back(i); } sort(mem[j].begin(),mem[j].end(),cmp); sum[j].resize(mem[j].size()); for(reg i=0;i<(int)mem[j].size();++i){ sum[j][i]=len[mem[j][i]]; con[j]+=(ll)len[mem[j][i]]*abs(pre[mem[j][i]]); if(i) sum[j][i]+=sum[j][i-1]; } tag[j]=0; ans+=con[j]; for(reg j=be[l]+1;j<=be[r]-1;++j){ pre[0]=-tag[j]; if(c==-1){ int lp=upper_bound(mem[j].begin(),mem[j].end(),0,cmp)-mem[j].begin(); --lp;//warning!! maybe -1 if(lp!=-1){ ans+=(ll)sum[j][lp]; ans-=(ll)sum[j][mem[j].size()-1]-sum[j][lp]; con[j]+=(ll)sum[j][lp]; con[j]-=(ll)sum[j][mem[j].size()-1]-sum[j][lp]; }else{ ans-=(ll)sum[j][mem[j].size()-1]; con[j]-=(ll)sum[j][mem[j].size()-1]; } }else{ int lp=lower_bound(mem[j].begin(),mem[j].end(),0,cmp)-mem[j].begin(); --lp;//warning!! maybe -1 if(lp!=-1){ ans-=(ll)sum[j][lp]; ans+=(ll)sum[j][mem[j].size()-1]-sum[j][lp]; con[j]-=(ll)sum[j][lp]; con[j]+=(ll)sum[j][mem[j].size()-1]-sum[j][lp]; }else{ ans+=(ll)sum[j][mem[j].size()-1]; con[j]+=(ll)sum[j][mem[j].size()-1]; } } tag[j]+=c; } pre[0]=0; } pos[q[o].id]=q[o].x; printf("%lld\n",ans); } return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2019/4/11 10:31:35 */