首先这题显然是线段树
0操作 区间直接赋值为0 很简单
2操作 统计最长连续0的个数 记录lx,rx,mx三个量,随便合并一下就行了,很简单
1操作……
首先需要记录一个sum表示当前区间有多少脑组织
然后二分填满的位置,我偷懒写了线段树外面的二分,然后时间复杂度就多了一个log
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int N=200005; int n,m; struct SegTree{ int lx,rx,mx,tag,sum,l,r; }tree[N<<2]; void Pushdown(int rt){ if(tree[rt].tag==1){ tree[rt<<1].tag=1; tree[rt<<1|1].tag=1; tree[rt<<1].lx=tree[rt<<1].rx=tree[rt<<1].mx=0; tree[rt<<1].sum=tree[rt<<1].r-tree[rt<<1].l+1; tree[rt<<1|1].lx=tree[rt<<1|1].rx=tree[rt<<1|1].mx=0; tree[rt<<1|1].sum=tree[rt<<1|1].r-tree[rt<<1|1].l+1; tree[rt].tag=0; } if(tree[rt].tag==-1){ tree[rt<<1].tag=-1; tree[rt<<1|1].tag=-1; tree[rt<<1].lx=tree[rt<<1].rx=tree[rt<<1].mx=tree[rt<<1].r-tree[rt<<1].l+1; tree[rt<<1].sum=0; tree[rt<<1|1].lx=tree[rt<<1|1].rx=tree[rt<<1|1].mx=tree[rt<<1|1].rx=tree[rt<<1|1].mx=tree[rt<<1|1].r-tree[rt<<1|1].l+1; tree[rt<<1|1].sum=0; tree[rt].tag=0; } } void Pushup(int rt){ tree[rt].mx=max(max(tree[rt<<1].mx,tree[rt<<1|1].mx),tree[rt<<1].rx+tree[rt<<1|1].lx); tree[rt].lx=tree[rt<<1].lx;tree[rt].rx=tree[rt<<1|1].rx; if(tree[rt<<1].lx==tree[rt<<1].r-tree[rt<<1].l+1)tree[rt].lx=tree[rt<<1].lx+tree[rt<<1|1].lx; if(tree[rt<<1|1].rx==tree[rt<<1|1].r-tree[rt<<1|1].l+1)tree[rt].rx=tree[rt<<1|1].rx+tree[rt<<1].rx; tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum; } void Build(int rt,int l,int r){ tree[rt].l=l;tree[rt].r=r; if(l==r){tree[rt].mx=tree[rt].lx=tree[rt].rx=0;tree[rt].sum=1;return;} int mid=l+r>>1; Build(rt<<1,l,mid); Build(rt<<1|1,mid+1,r); Pushup(rt); } void Update(int rt,int l,int r,int val){ if(l<=tree[rt].l && tree[rt].r<=r){ tree[rt].tag=val; if(val==-1){tree[rt].lx=tree[rt].rx=tree[rt].mx=tree[rt].r-tree[rt].l+1;tree[rt].sum=0;} if(val==1){tree[rt].lx=tree[rt].rx=tree[rt].mx=0;tree[rt].sum=tree[rt].r-tree[rt].l+1;} return; } Pushdown(rt); int mid=tree[rt].l+tree[rt].r>>1; if(l<=mid)Update(rt<<1,l,r,val); if(r>mid)Update(rt<<1|1,l,r,val); Pushup(rt); } int GetSum(int rt,int l,int r){ if(l<=tree[rt].l & tree[rt].r<=r)return tree[rt].sum; Pushdown(rt); int mid=tree[rt].l+tree[rt].r>>1; if(l>mid)return GetSum(rt<<1|1,l,r); else if(r<=mid)return GetSum(rt<<1,l,r); else return GetSum(rt<<1,l,r)+GetSum(rt<<1|1,l,r); Pushup(rt); } void Solve(int l0,int r0,int l1,int r1){ int ResL=GetSum(1,l0,r0); Update(1,l0,r0,-1); int ResR=GetSum(1,l1,r1); //printf("Res:%d %d\n",ResL,ResR); if(ResL+ResR>=r1-l1+1){Update(1,l1,r1,1);/*puts("666!");*/} else { int l=l1,r=r1; while(l<=r){ int mid=l+r>>1,t=GetSum(1,l1,mid); if(mid-l1+1-t==ResL){Update(1,l1,mid,1);return;} else if(mid-l1+1<ResL+t)l=mid+1; else if(mid-l1+1>ResL+t)r=mid-1; } } } SegTree Merge(SegTree L,SegTree R){ SegTree M; M.mx=max(max(L.mx,R.mx),L.rx+R.lx); M.lx=L.lx;M.rx=R.rx; if(L.sum==0)M.lx=L.lx+R.lx; if(R.sum==0)M.rx=L.rx+R.rx; M.sum=max(L.sum,R.sum); return M; } SegTree GetMax(int rt,int l,int r){ if(l<=tree[rt].l && tree[rt].r<=r)return tree[rt]; Pushdown(rt); int mid=tree[rt].l+tree[rt].r>>1; if(l>mid)return GetMax(rt<<1|1,l,r); else if(r<=mid)return GetMax(rt<<1,l,r); else {return Merge(GetMax(rt<<1,l,r),GetMax(rt<<1|1,l,r));} Pushup(rt); } void Print(){ //puts("233:"); for(int i=1;i<=n;i++)printf("%d ",GetSum(1,i,i)); putchar('\n'); } int main(){ freopen("4592.in","r",stdin); freopen("4592.out","w",stdout); scanf("%d %d",&n,&m); Build(1,1,n); //Print(); for(int i=1;i<=m;i++){ int opt,l0,r0,l1,r1; scanf("%d %d %d",&opt,&l0,&r0); if(opt==1)scanf("%d %d",&l1,&r1); if(opt==0)Update(1,l0,r0,-1); if(opt==1)Solve(l0,r0,l1,r1); if(opt==2)printf("%d\n",GetMax(1,l0,r0).mx); //Print(); } return 0; }