本题目重做感受颇多,
思考的深度决定了对线段树的掌握程度,只有自己创生的才是自己的啊。
本题用到了三个维护值,sum表示区间最长连续区间,lsum为区间左面最长连续区间长。rsum同理。
现在来说明sum为什么具有 可维护性,
线段树的可维护性是相对于更新区间而言的,因为更新的logn个区间总是被刷成全空房间,或全满房间,所以这几个区间的三个属性都可以得到维护,并且具有向上的合并性质
所以可以维护,一旦可以维护,那就啥也不说了。
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define rep(i,n) for(int (i)=0;(i)<(n);i++) #define Rep(i,n) for(int (i)=1;(i)<=(n);i++) const int N = 51111; int sum[N<<2],col[N<<2],lsum[N<<2],rsum[N<<2]; void push_up(int l,int r,int rt){ sum[rt] = max(sum[rt<<1],sum[rt<<1|1]); sum[rt] = max(sum[rt],rsum[rt<<1]+lsum[rt<<1|1]); int v = lsum[rt<<1]; int m = (l+r)>>1; lsum[rt] = (v==m-l+1 ? v+lsum[rt<<1|1]:v); v = rsum[rt<<1|1]; rsum[rt] = (v==r-m ? v+rsum[rt<<1]:v); } void upd_one_seg(int l,int r,int rt,int f){ if(!f){ sum[rt] = lsum[rt] = rsum[rt] = r-l+1; } else { sum[rt] = lsum[rt] = rsum[rt] = 0; } } void push_down(int l,int r,int rt){ if(col[rt]!=-1){ int m = (l+r)>>1; upd_one_seg(lson,col[rt]); upd_one_seg(rson,col[rt]); col[rt<<1] = col[rt<<1|1] = col[rt]; col[rt] = -1; } } void build(int l,int r,int rt){ col[rt] = -1; if(l==r){ sum[rt] = lsum[rt] = rsum[rt] = 1; return ; } int m = (l+r)>>1; build(lson); build(rson); push_up(l,r,rt); } void update(int l,int r,int rt,int L,int R,int f){ if(L<=l&&r<=R){ col[rt] = f; upd_one_seg(l,r,rt,f); return ; } push_down(l,r,rt); int m = (l+r)>>1; if(L<=m) update(lson,L,R,f); if(R>m) update(rson,L,R,f); push_up(l,r,rt); } int query(int l,int r,int rt,int len){ if(l==r){ if(sum[rt] == len) return l; return 0; } push_down(l,r,rt); int m = (l+r)>>1; if(sum[rt<<1]>=len) return query(lson,len); int mid = rsum[rt<<1]+lsum[rt<<1|1]; if(mid >= len){return m-rsum[rt<<1]+1;} else if(sum[rt<<1|1]>=len) return query(rson,len); return 0; } int n,m; int main() { while(scanf("%d %d",&n,&m)==2){ build(1,n,1); while(m--){ int cmd,x,y; scanf("%d",&cmd); if(cmd == 1){ scanf("%d",&x); int p = query(1,n,1,x); printf("%d\n",p); if(p){ update(1,n,1,p,p+x-1,1); } } else { scanf("%d %d",&x,&y); update(1,n,1,x,x+y-1,0); } } } return 0; }