【bzoj4592】[Shoi2015]脑洞治疗仪
由于脑洞的序列不会改变,考虑用线段树维护区间内sum,左边0的个数,右边0的个数,区间内最大脑洞。对于查询l~r最大脑洞可以将l~r分成logn个区间,总复杂度O(nlogn)。
#include<iostream> #include<cstdio> #include<cstdlib> #define N 800005 using namespace std; int n,m,p,x,y,l,r; int sum[N],L[N],R[N],tg[N],v[N],Ans[N],rest,Hz,ans; void down(int k) { if (tg[k]!=-1) { int l=k<<1,r=l|1; tg[l]=tg[r]=tg[k]; sum[l]=v[l]*tg[k]; sum[r]=v[r]*tg[k]; if (tg[k]==0) L[l]=R[l]=Ans[l]=v[l],L[r]=R[r]=Ans[r]=v[r]; else L[l]=R[l]=L[r]=Ans[l]=R[r]=Ans[r]=0; tg[k]=-1; } } void up(int k) { int l=k<<1,r=l|1;sum[k]=sum[l]+sum[r]; if (!sum[l]) L[k]=L[l]+L[r];else L[k]=L[l]; if (!sum[r]) R[k]=R[l]+R[r];else R[k]=R[r]; Ans[k]=max(max(Ans[l],Ans[r]),R[l]+L[r]); } void build(int k,int l,int r) { if (l==r){v[k]=1;return;} int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); v[k]=v[k<<1]+v[k<<1|1]; } void add(int k,int l,int r,int x,int y) { if (x<=l&&r<=y) { sum[k]=0;tg[k]=0; L[k]=R[k]=v[k]; return; } int mid=(l+r)>>1; down(k); if (x<=mid) add(k<<1,l,mid,x,y); if (y>mid) add(k<<1|1,mid+1,r,x,y); up(k); } int Get(int k,int l,int r,int x,int y) { if (x<=l&&r<=y) return sum[k]; int mid=(l+r)>>1; down(k); int Ans=0; if (x<=mid) Ans+=Get(k<<1,l,mid,x,y); if (y>mid) Ans+=Get(k<<1|1,mid+1,r,x,y); return Ans; } void fix(int k,int l,int r,int x,int y) { if (!rest) return; if (x<=l&&r<=y&&rest>=v[k]-sum[k]) { rest-=v[k]-sum[k]; tg[k]=1;Ans[k]=0; L[k]=R[k]=0;sum[k]=v[k]; return; } down(k); int mid=(l+r)>>1; if (x<=mid) fix(k<<1,l,mid,x,y); if (y>mid) fix(k<<1|1,mid+1,r,x,y); up(k); } void qry(int k,int l,int r,int x,int y) { if (x<=l&&r<=y) { ans=max(ans,Ans[k]); ans=max(ans,Hz+L[k]); if (R[k]==v[k]) Hz+=R[k];else Hz=R[k]; return; } down(k); int mid=(l+r)>>1; if (x<=mid) qry(k<<1,l,mid,x,y); if (y>mid) qry(k<<1|1,mid+1,r,x,y); } int main() { scanf("%d%d",&n,&m); build(1,1,n); sum[1]=v[1];tg[1]=1; for (int i=1;i<=m;i++) { scanf("%d%d%d",&p,&l,&r); if (p==0) add(1,1,n,l,r); else if (p==1) { scanf("%d%d",&x,&y); rest=Get(1,1,n,l,r); add(1,1,n,l,r); fix(1,1,n,x,y); } else { ans=0;Hz=0;qry(1,1,n,l,r); printf("%d\n",ans); } } return 0; }