第一眼看成了一个裸的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;
}
(我必须承认最开始我想的是再来一层二分。。。)