[BZOJ4592][SHOI2015]脑洞治疗仪(线段树)

时间:2024-01-15 11:33:20

线段树基础操作题,唯一需要思考下的是将区间的前k个0覆盖为1。

线段树上二分,先递归到左子树覆盖,回溯时返回还剩多少个0未被覆盖,在根据这个信息递归到右子树。注意特判k=0的情况。

要维护的信息有:区间左边最长0连续段,右边最长0连续段,区间整体最长0连续段,区间内1的个数,以及一个记录是否被区间覆盖的懒惰标记。

 #include<cstdio>
#include<algorithm>
#define ls (x<<1)
#define rs (ls|1)
#define lson ls,L,mid
#define rson rs,mid+1,R
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
using namespace std; const int N=;
int n,m,op,l,r,l1,r1,l2,r2,mx[N<<],mxl[N<<],mxr[N<<],cnt[N<<],tag[N<<]; void build(int x,int L,int R){
int mid=(L+R)>>;
tag[x]=-; cnt[x]=R-L+;
if (L==R) return;
build(lson); build(rson);
} void upd(int x,int L,int R){
int mid=(L+R)>>;
mxl[x]=mxl[ls]+(mxl[ls]==mid-L+ ? mxl[rs] : );
mxr[x]=mxr[rs]+(mxr[rs]==R-mid ? mxr[ls] : );
mx[x]=max(max(mx[ls],mx[rs]),mxr[ls]+mxl[rs]);
cnt[x]=cnt[ls]+cnt[rs];
} void put(int x,int L,int R,int k){
if (!k) mxl[x]=mxr[x]=mx[x]=R-L+,cnt[x]=,tag[x]=k;
else mxl[x]=mxr[x]=mx[x]=,cnt[x]=R-L+,tag[x]=k;
} void push(int x,int L,int R){
int mid=(L+R)>>;
if (~tag[x]) put(ls,L,mid,tag[x]),put(rs,mid+,R,tag[x]),tag[x]=-;
} void mdf(int x,int L,int R,int l,int r,int k){
if (L==l && r==R){ put(x,L,R,k); return; }
int mid=(L+R)>>; push(x,L,R);
if (r<=mid) mdf(lson,l,r,k);
else if (l>mid) mdf(rson,l,r,k);
else mdf(lson,l,mid,k),mdf(rson,mid+,r,k);
upd(x,L,R);
} int que(int x,int L,int R,int l,int r){
if (L==l && r==R) return cnt[x];
int mid=(L+R)>>; push(x,L,R);
if (r<=mid) return que(lson,l,r);
else if (l>mid) return que(rson,l,r);
else return que(lson,l,mid)+que(rson,mid+,r);
} int paint(int x,int L,int R,int l,int r,int k){
if (!k) return ;
if (L==l && r==R && R-L+-cnt[x]<=k){ k-=R-L+-cnt[x]; put(x,L,R,); return k; }
int mid=(L+R)>>; push(x,L,R);
if (r<=mid) k=paint(lson,l,r,k);
else if (l>mid) k=paint(rson,l,r,k);
else{
int t=paint(lson,l,mid,k);
if (t) k=paint(rson,mid+,r,t); else k=;
}
upd(x,L,R); return k;
} int get(int x,int L,int R,int l,int r){
if (L==l && r==R) return mx[x];
int mid=(L+R)>>; push(x,L,R);
if (r<=mid) return get(lson,l,r);
else if (l>mid) return get(rson,l,r);
else return max(max(get(lson,l,mid),get(rson,mid+,r)),min(mxr[ls],mid-l+)+min(mxl[rs],r-mid));
} int main(){
freopen("bzoj4592.in","r",stdin);
freopen("bzoj4592.out","w",stdout);
scanf("%d%d",&n,&m); build(,,n);
rep(i,,m){
scanf("%d",&op);
if (op==) scanf("%d%d",&l,&r),mdf(,,n,l,r,);
if (op==){
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
int t=que(,,n,l1,r1); mdf(,,n,l1,r1,);
paint(,,n,l2,r2,t);
}
if (op==) scanf("%d%d",&l,&r),printf("%d\n",get(,,n,l,r));
//rep(i,1,n) printf("%d ",que(1,1,n,i,i)); puts("");
}
return ;
}