BZOJ4592: [Shoi2015]脑洞治疗仪(洛谷P4344)
线段树
昨天一个字母打错一晚上没调出来。。。
挺裸的线段树。
0直接做。1记录下 l0 l 0 到 r0 r 0 的1的个数后可以二分确定修补的右端点,也可以直接往下做到没有为止,前者 log2 log 2 ,后者比 log log 稍微大一点。2对每个节点记一下最左边、最右边、最大的脑洞的长度,查询的时候直接合并就好了,稍微有点细节。
代码:
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 200005
#define F inline
using namespace std;
struct tree{ int mx,s,lx,rx,l,r,f; }t[N<<2];
int n,m,k,s;
F char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
return l==r?EOF:*l++;
}
F int _read(){
int x=0; char ch=readc();
while (!isdigit(ch)) ch=readc();
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
return x;
}
F void writec(int x){ if (x>9) writec(x/10); putchar(x%10+48); }
F void _write(int x){ writec(x),puts(""); }
void build(int x,int l,int r){
t[x].l=l,t[x].r=r,t[x].f=-1;
if (l==r) return; int mid=l+r>>1;
build(x<<1,l,mid),build(x<<1|1,mid+1,r);
}
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
F void pshp(int x){
int l=x<<1,r=x<<1|1; t[x].s=t[l].s+t[r].s;
t[x].mx=max(max(t[l].mx,t[r].mx),t[l].rx+t[r].lx);
t[x].lx=t[l].lx,t[x].rx=t[r].rx;
if (t[l].mx==t[l].r-t[l].l+1) t[x].lx+=t[r].lx;
if (t[r].mx==t[r].r-t[r].l+1) t[x].rx+=t[l].rx;
}
F void pshd(int x){
int w=t[x].f,l=x<<1,r=x<<1|1;
t[x].f=-1,t[l].f=t[r].f=w;
t[l].lx=t[l].rx=t[l].mx=t[l].s=(w^1)*(t[l].r-t[l].l+1);
t[r].lx=t[r].rx=t[r].mx=t[r].s=(w^1)*(t[r].r-t[r].l+1);
}
void mdfy(int x,int l,int r){
if (t[x].l>r||t[x].r<l) return;
if (t[x].l>=l&&t[x].r<=r){
t[x].lx=t[x].rx=t[x].mx=t[x].s=t[x].r-t[x].l+1;
t[x].f=0; return;
}
if (~t[x].f) pshd(x);
mdfy(x<<1,l,r),mdfy(x<<1|1,l,r),pshp(x);
}
tree srch(int x,int l,int r){
tree xs={0,0,0,0},ls,rs;
if (t[x].l>r||t[x].r<l) return xs;
if (t[x].l>=l&&t[x].r<=r) return t[x];
if (~t[x].f) pshd(x);
ls=srch(x<<1,l,r),rs=srch(x<<1|1,l,r);
xs.mx=max(max(ls.mx,rs.mx),ls.rx+rs.lx);
xs.lx=ls.lx,xs.rx=rs.rx;
if (ls.lx==min(r,t[x<<1].r)-max(l,t[x<<1].l)+1)
xs.lx+=rs.lx;
if (rs.rx==min(r,t[x<<1|1].r)-max(l,t[x<<1|1].l)+1)
xs.rx+=ls.rx;
xs.s=ls.s+rs.s; return xs;
}
void chng(int x,int l,int r){
if (t[x].l>r||t[x].r<l||s==0) return;
if (t[x].l>=l&&t[x].r<=r)
if (s>=t[x].s){
s-=t[x].s,t[x].f=1;
t[x].lx=t[x].rx=t[x].mx=t[x].s=0; return;
}
if (~t[x].f) pshd(x);
chng(x<<1,l,r),chng(x<<1|1,l,r),pshp(x);
}
int main(){
for (n=_read(),m=_read(),build(1,1,n);m;m--){
int f=_read(),l=_read(),r=_read(),L,R;
if (f==0) mdfy(1,l,r);
else if (f==1){
L=_read(),R=_read(),s=r-l+1-srch(1,l,r).s;
mdfy(1,l,r),chng(1,L,R);
}
else _write(srch(1,l,r).mx);
}
return 0;
}