【BZOJ4592】【Shoi2015】腦洞治療儀 線段樹
阿新 • • 發佈:2018-12-24
第一眼看成了一個裸的01弱智線段樹,然後發現弱智的是自己。。。主要就是如果好腦洞不夠用了就儘量往前面補這一個操作。。。
其實還是不難。。。我們線上段樹遍歷的時候優先往前面補,如果這個區間不夠補就分別檢查兩個子區間,可以證明這樣的操作還是log級別的(反正我不會233),然後就是最長連續區間的套路辣
(我必須承認最開始我想的是再來一層二分。。。)/************************************************************** Problem: 4592 User: RicardoWang Language: C++ Result: Accepted Time:13220 ms Memory:32528 kb ****************************************************************/ #include<cstdlib> #include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<vector> using namespace std; void _read(int &x) { x=0; char ch=getchar(); bool flag=false; while(ch<'0' || ch>'9'){if(ch=='-')flag=true;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} if(flag)x=-x;return ; } #define MAXN 400005 struct data { int L,R,Sum0,Sum1,lmax,rmax,max; }w[MAXN*2]; int N,M,np,rt,chi[2*MAXN][2],down[MAXN*2]; void pushup(data &now,data lc,data rc) { now=(data){lc.L,rc.R,lc.Sum0+rc.Sum0,lc.Sum1+rc.Sum1,lc.lmax,rc.rmax,max(lc.rmax+rc.lmax,max(lc.max,rc.max))}; if(lc.Sum1==0)now.lmax+=rc.lmax; if(rc.Sum1==0)now.rmax+=lc.rmax; return ; } void add(data &x,int v) { int L=x.L,R=x.R; if(v==0) { x=(data){L,R,R-L+1,0,R-L+1,R-L+1,R-L+1}; } else { x=(data){L,R,0,R-L+1,0,0,0}; } return ; } void pushdown(int now) { if(down[now]>0) { // data &lc=w[chi[now][0]],&rc=w[chi[now][1]]; if(down[now]==1) { add(w[chi[now][0]],0);//lc=(data){lc.L,lc.R,lc.R-lc.L+1,0,lc.R-lc.L+1,lc.R-lc.L+1,lc.R-lc.L+1}; add(w[chi[now][1]],0);//rc=(data){rc.L,rc.R,rc.R-rc.L+1,0,rc.R-rc.L+1,rc.R-rc.L+1,rc.R-rc.L+1}; down[chi[now][0]]=down[chi[now][1]]=1; } else { add(w[chi[now][0]],1);//lc=(data){lc.L,lc.R,0,lc.R-lc.L+1,0,0,0}; add(w[chi[now][1]],1);//rc=(data){rc.L,rc.R,0,rc.R-rc.L+1,0,0,0}; down[chi[now][0]]=down[chi[now][1]]=2; } down[now]=0; } return ; } void build(int &now,int L,int R) { now=++np; if(L==R) { w[now]=(data){L,R,0,1,0,0,0}; return ; } int m=(L+R)>>1; build(chi[now][0],L,m); build(chi[now][1],m+1,R); pushup(w[now],w[chi[now][0]],w[chi[now][1]]); return ; } void update(int now,int L,int R,int x,int y,int v) { if(x>y)return ; if(x<=L && R<=y) { down[now]=v+1; add(w[now],v); return ; } int m=(L+R)>>1; pushdown(now); if(x<=m)update(chi[now][0],L,m,x,y,v); if(y> m)update(chi[now][1],m+1,R,x,y,v); pushup(w[now],w[chi[now][0]],w[chi[now][1]]); return ; } int Num; void fix(int now,int L,int R,int x,int y) { if(!Num)return ; if(x<=L && R<=y && Num>=w[now].Sum0) { Num-=w[now].Sum0; add(w[now],1); down[now]=2; return ; } int m=(L+R)>>1; pushdown(now); if(x<=m)fix(chi[now][0],L,m,x,y); if(y> m)fix(chi[now][1],m+1,R,x,y); pushup(w[now],w[chi[now][0]],w[chi[now][1]]); return ; } data query(int now,int L,int R,int x,int y) { if(x<=L && R<=y) { return w[now]; } pushdown(now); //pushup(w[now],w[chi[now][0]],w[chi[now][1]]); int m=(L+R)>>1; if(y<=m) { return query(chi[now][0],L,m,x,y); } else if(x>m) { return query(chi[now][1],m+1,R,x,y); } else { data t; pushup(t,query(chi[now][0],L,m,x,y),query(chi[now][1],m+1,R,x,y)); return t; } } void Debug(data x) { // printf("%d %d : %d %d %d %d %d\n",x.L,x.R,x.Sum0,x.Sum1,x.lmax,x.rmax,x.max); return ; } void Debug2() { /* data t; for(int i=1;i<=N;i++) { t=query(rt,1,N,i,i); printf("%d ",t.Sum1); } putchar('\n');*/ } void work() { _read(N);_read(M); build(rt,1,N); char op;int xa,ya,xb,yb,L,R,mid,ans;data A,B,C; for(int i=1;i<=M;i++) { op=getchar(); while(op!='0' && op!='1' && op!='2')op=getchar(); if(op=='0') { _read(xa); _read(ya); update(rt,1,N,xa,ya,0); } else if(op=='1') { _read(xa); _read(ya); A=query(rt,1,N,xa,ya); _read(xb); _read(yb); B=query(rt,1,N,xb,yb); update(rt,1,N,xa,ya,0); Num=A.Sum1; fix(rt,1,N,xb,yb); } else { _read(xa); _read(ya); A=query(rt,1,N,xa,ya); // Debug(A); printf("%d\n",A.max); } // Debug2(); } return ; } int main() { //freopen("in.txt","r",stdin); work(); return 0; }