題意
曾經發明了自動刷題機的發明家SHTSC又公開了他的新發明:腦洞治療儀–一種可以治療他因為發明而日益增大的腦洞的神秘裝置。
為了簡單起見,我們將大腦視作一個01序列。1代表這個位置的腦組織正常工作,0代表這是一塊腦洞。
1 0 1 0 0 0 1 1 1 0
腦洞治療儀修補某一塊腦洞的基本工作原理就是將另一塊連續地區挖出,將其中正常工作的腦組織填補在這塊腦洞中。
(所以腦洞治療儀是腦洞的治療儀。)
例如,用上面第8號位置到第10號位置去修補第1號位置到第4號位置的腦洞。我們就會得到:
1 1 1 1 0 0 1 0 0 0
如果再用第1號位置到第4號位置去修補第8號位置到第10號位置:
0 0 0 0 0 0 1 1 1 1
這是因為腦洞治療儀會把多餘出來的腦組織直接扔掉。
如果再用第7號位置到第10號位置去填補第1號位置到第6號位置:
1 1 1 1 0 0 0 0 0 0
這是因為如果新腦洞挖出來的腦組織不夠多,腦洞治療儀僅會盡量填補位置比較靠前的腦洞。
假定初始時SHTSC並沒有腦洞,給出一些挖腦洞和腦洞治療的操作序列,你需要即時回答SHTSC的問題:
在大腦某個區間中最大的連續腦洞地區有多大。
n,m <=200000,1<=l<=r<=n 分析
直接上線段樹即可。 代碼
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;const int N=200005;int n,m;struct tree{int s0,s1,ls,rs,tag,mx;}t[N*5];int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}void pushdown(int d,int l,int r){ if (l==r||t[d].tag==-1) return; int mid=(l+r)/2; if (!t[d].tag) { t[d*2].tag=t[d*2+1].tag=t[d*2].s1=t[d*2+1].s1=0; t[d*2].s0=t[d*2].ls=t[d*2].rs=t[d*2].mx=mid-l+1; t[d*2+1].s0=t[d*2+1].ls=t[d*2+1].rs=t[d*2+1].mx=r-mid; } else { t[d*2].tag=t[d*2+1].tag=1; t[d*2].s1=mid-l+1;t[d*2+1].s1=r-mid; t[d*2].s0=t[d*2].ls=t[d*2].rs=t[d*2].mx=0; t[d*2+1].s0=t[d*2+1].ls=t[d*2+1].rs=t[d*2+1].mx=0; } t[d].tag=-1;}tree merge(tree x,tree y){ tree u;u.tag=-1; u.s0=x.s0+y.s0;u.s1=x.s1+y.s1; u.ls=x.ls==x.s0+x.s1?x.ls+y.ls:x.ls; u.rs=y.rs==y.s0+y.s1?y.rs+x.rs:y.rs; u.mx=max(max(x.mx,y.mx),x.rs+y.ls); return u;}void build(int d,int l,int r){ t[d].s1=r-l+1;t[d].tag=-1; if (l==r) return; int mid=(l+r)/2; build(d*2,l,mid);build(d*2+1,mid+1,r);}void modify(int d,int l,int r,int x,int y,int z){ if (x>y) return; pushdown(d,l,r); if (l==x&&r==y) { if (!z) t[d].tag=0,t[d].mx=t[d].ls=t[d].rs=t[d].s0=r-l+1,t[d].s1=0; else t[d].tag=1,t[d].mx=t[d].ls=t[d].rs=t[d].s0=0,t[d].s1=r-l+1; return; } int mid=(l+r)/2; modify(d*2,l,mid,x,min(y,mid),z); modify(d*2+1,mid+1,r,max(x,mid+1),y,z); t[d]=merge(t[d*2],t[d*2+1]);}int get_s0(int d,int l,int r,int x,int y){ if (x>y) return 0; pushdown(d,l,r); if (l==x&&r==y) return t[d].s0; int mid=(l+r)/2; return get_s0(d*2,l,mid,x,min(y,mid))+get_s0(d*2+1,mid+1,r,max(x,mid+1),y);}int get_s1(int d,int l,int r,int x,int y){ if (x>y) return 0; pushdown(d,l,r); if (l==x&&r==y) return t[d].s1; int mid=(l+r)/2; return get_s1(d*2,l,mid,x,min(y,mid))+get_s1(d*2+1,mid+1,r,max(x,mid+1),y);}int get_p(int d,int l,int r,int k){ if (l==r) return l; pushdown(d,l,r); int mid=(l+r)/2; if (t[d*2].s0>=k) return get_p(d*2,l,mid,k); else return get_p(d*2+1,mid+1,r,k-t[d*2].s0);}tree query(int d,int l,int r,int x,int y){ pushdown(d,l,r); if (l==x&&r==y) return t[d]; int mid=(l+r)/2; if (y<=mid) return query(d*2,l,mid,x,y); else if (x>mid) return query(d*2+1,mid+1,r,x,y); else return merge(query(d*2,l,mid,x,mid),query(d*2+1,mid+1,r,mid+1,y));}int main(){ n=read();m=read(); build(1,1,n); while (m--) { int op=read(); if (!op) { int l=read(),r=read(); modify(1,1,n,l,r,0); } else if (op==1) { int l0=read(),r0=read(),l1=read(),r1=read(); int s1=get_s1(1,1,n,l0,r0);modify(1,1,n,l0,r0,0); int s0=get_s0(1,1,n,1,l1-1),p=get_p(1,1,n,min(s0+s1,get_s0(1,1,n,1,r1))); if (min(s0+s1,get_s0(1,1,n,1,r1))) modify(1,1,n,l1,p,1); } else { int l=read(),r=read(); printf("%d\n",query(1,1,n,l,r).mx); } } return 0;}