[BZOJ4592][SHOI2015]脑洞治疗仪(线段树)
线段树基础操作题,唯一需要思考下的是将区间的前k个0覆盖为1。
线段树上二分,先递归到左子树覆盖,回溯时返回还剩多少个0未被覆盖,在根据这个信息递归到右子树。注意特判k=0的情况。
要维护的信息有:区间左边最长0连续段,右边最长0连续段,区间整体最长0连续段,区间内1的个数,以及一个记录是否被区间覆盖的懒惰标记。
1 #include<cstdio> 2 #include<algorithm> 3 #define ls (x<<1) 4 #define rs (ls|1) 5 #define lson ls,L,mid 6 #define rson rs,mid+1,R 7 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 8 using namespace std; 9 10 const int N=200010; 11 int n,m,op,l,r,l1,r1,l2,r2,mx[N<<2],mxl[N<<2],mxr[N<<2],cnt[N<<2],tag[N<<2]; 12 13 void build(int x,int L,int R){ 14 int mid=(L+R)>>1; 15 tag[x]=-1; cnt[x]=R-L+1; 16 if (L==R) return; 17 build(lson); build(rson); 18 } 19 20 void upd(int x,int L,int R){ 21 int mid=(L+R)>>1; 22 mxl[x]=mxl[ls]+(mxl[ls]==mid-L+1 ? mxl[rs] : 0); 23 mxr[x]=mxr[rs]+(mxr[rs]==R-mid ? mxr[ls] : 0); 24 mx[x]=max(max(mx[ls],mx[rs]),mxr[ls]+mxl[rs]); 25 cnt[x]=cnt[ls]+cnt[rs]; 26 } 27 28 void put(int x,int L,int R,int k){ 29 if (!k) mxl[x]=mxr[x]=mx[x]=R-L+1,cnt[x]=0,tag[x]=k; 30 else mxl[x]=mxr[x]=mx[x]=0,cnt[x]=R-L+1,tag[x]=k; 31 } 32 33 void push(int x,int L,int R){ 34 int mid=(L+R)>>1; 35 if (~tag[x]) put(ls,L,mid,tag[x]),put(rs,mid+1,R,tag[x]),tag[x]=-1; 36 } 37 38 void mdf(int x,int L,int R,int l,int r,int k){ 39 if (L==l && r==R){ put(x,L,R,k); return; } 40 int mid=(L+R)>>1; push(x,L,R); 41 if (r<=mid) mdf(lson,l,r,k); 42 else if (l>mid) mdf(rson,l,r,k); 43 else mdf(lson,l,mid,k),mdf(rson,mid+1,r,k); 44 upd(x,L,R); 45 } 46 47 int que(int x,int L,int R,int l,int r){ 48 if (L==l && r==R) return cnt[x]; 49 int mid=(L+R)>>1; push(x,L,R); 50 if (r<=mid) return que(lson,l,r); 51 else if (l>mid) return que(rson,l,r); 52 else return que(lson,l,mid)+que(rson,mid+1,r); 53 } 54 55 int paint(int x,int L,int R,int l,int r,int k){ 56 if (!k) return 0; 57 if (L==l && r==R && R-L+1-cnt[x]<=k){ k-=R-L+1-cnt[x]; put(x,L,R,1); return k; } 58 int mid=(L+R)>>1; push(x,L,R); 59 if (r<=mid) k=paint(lson,l,r,k); 60 else if (l>mid) k=paint(rson,l,r,k); 61 else{ 62 int t=paint(lson,l,mid,k); 63 if (t) k=paint(rson,mid+1,r,t); else k=0; 64 } 65 upd(x,L,R); return k; 66 } 67 68 int get(int x,int L,int R,int l,int r){ 69 if (L==l && r==R) return mx[x]; 70 int mid=(L+R)>>1; push(x,L,R); 71 if (r<=mid) return get(lson,l,r); 72 else if (l>mid) return get(rson,l,r); 73 else return max(max(get(lson,l,mid),get(rson,mid+1,r)),min(mxr[ls],mid-l+1)+min(mxl[rs],r-mid)); 74 } 75 76 int main(){ 77 freopen("bzoj4592.in","r",stdin); 78 freopen("bzoj4592.out","w",stdout); 79 scanf("%d%d",&n,&m); build(1,1,n); 80 rep(i,1,m){ 81 scanf("%d",&op); 82 if (op==0) scanf("%d%d",&l,&r),mdf(1,1,n,l,r,0); 83 if (op==1){ 84 scanf("%d%d%d%d",&l1,&r1,&l2,&r2); 85 int t=que(1,1,n,l1,r1); mdf(1,1,n,l1,r1,0); 86 paint(1,1,n,l2,r2,t); 87 } 88 if (op==2) scanf("%d%d",&l,&r),printf("%d\n",get(1,1,n,l,r)); 89 //rep(i,1,n) printf("%d ",que(1,1,n,i,i)); puts(""); 90 } 91 return 0; 92 }