Poj--3667(线段树,经典各种操作)

2014-10-01 23:19:30

思路:这题可以说是线段树各种操作的集大成者,包含区间更新,区间最值,lazy思想等。和poj1823是姐妹篇。

  这题的几个点:

(1)每个节点维护一个cover值,-1表示全空,1表示全满,0表示一部分空(建树时预设全空:-1)

  每个节点维护三个长度值:llen表示从头开始连续空的长度,rlen表示从尾开始连续空的长度,tmax表示这个区间最长连续空的长度。

  每个节点维护一个pos值:记录这个区间最长连续空的开始位置。

(2)pushdown操作只针对当前区间全空 / 全满的情况,第三种情况在递归完左右子树后再考虑。

(3)每次Update更新完后,对当前节点的所有维护信息都要更新。

(4)在Query查询时找k长连续空区间,考虑的顺序:1、llen>=k  , 2、leftson-tmax >= k , 3、leftson-rlen + rightson-llen >= k ,4、rightson-tmax >= k

  1 /*************************************************************************
  2     > File Name: 3667.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com 
  5     > Created Time: Wed 01 Oct 2014 08:53:44 PM CST
  6 ************************************************************************/
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <vector>
 13 #include <queue>
 14 #include <iostream>
 15 #include <algorithm>
 16 using namespace std;
 17 #define lp (p << 1)
 18 #define rp (p << 1|1)
 19 #define getmid(l,r) (l + (r - l) / 2)
 20 typedef long long ll;
 21 const int INF = 1 << 30;
 22 const int maxn = 50010;
 23 
 24 int N,M,ans;
 25 
 26 struct node{
 27     int l,r;
 28     int tmax,pos;
 29     int llen,rlen;
 30     int cover;//-1 : 全空,0:非全空非全满,1:全满
 31 }t[maxn << 2];
 32 
 33 void Build_tree(int p,int l,int r){
 34     t[p].l = l;
 35     t[p].r = r;
 36     t[p].cover = -1;
 37     t[p].tmax = t[p].llen = t[p].rlen = r - l + 1;
 38     t[p].pos = l;
 39     if(l == r)
 40         return;
 41     int mid = getmid(l,r);
 42     Build_tree(lp,l,mid);
 43     Build_tree(rp,mid + 1,r);
 44 }
 45 
 46 void Push_down(int p,int c){
 47     t[lp].cover = t[rp].cover = c;
 48     t[p].cover = 0;
 49     if(c == -1){
 50         t[lp].tmax = t[lp].llen = t[lp].rlen = t[lp].r - t[lp].l + 1;
 51         t[rp].tmax = t[rp].llen = t[rp].rlen = t[rp].r - t[rp].l + 1;
 52         t[lp].pos = t[lp].l;
 53         t[rp].pos = t[rp].l;
 54     }
 55     else{
 56         t[lp].tmax = t[lp].llen = t[lp].rlen = 0;
 57         t[rp].tmax = t[rp].llen = t[rp].rlen = 0;
 58     }
 59 }
 60 
 61 void Update_tree(int a,int b,int c,int p,int l,int r){
 62     if(a <= l && r <= b){
 63         t[p].cover = c;
 64         if(t[p].cover == -1){
 65             t[p].tmax = t[p].llen = t[p].rlen = t[p].r - t[p].l + 1;
 66             t[p].pos = t[p].l;
 67         }
 68         else{
 69             t[p].tmax = t[p].llen = t[p].rlen = 0;
 70         }
 71         return;
 72     }
 73     if(t[p].cover == c) return;
 74     else if(t[p].cover == -c) Push_down(p,-c); //(-1) -> 1 or 1 -> (-1)
 75     int mid = getmid(l,r);
 76     if(a <= mid)
 77         Update_tree(a,b,c,lp,l,mid);
 78     if(b > mid)
 79         Update_tree(a,b,c,rp,mid + 1,r);
 80     //Maintain
 81     t[p].llen = t[lp].llen;
 82     if(t[lp].cover == -1)
 83         t[p].llen += t[rp].llen;
 84     t[p].rlen = t[rp].rlen;
 85     if(t[rp].cover == -1)
 86         t[p].rlen += t[lp].rlen;
 87     
 88     int d1 = t[lp].rlen + t[rp].llen;
 89     int d2 = max(t[lp].tmax,t[rp].tmax);
 90     int d3 = max(t[p].llen,t[p].rlen);
 91     t[p].tmax = max(d1,max(d2,d3));
 92     t[p].pos = INF;
 93     if(t[p].tmax == t[p].llen)
 94         t[p].pos = min(t[p].pos,t[p].l);
 95     if(t[p].tmax == t[p].rlen)
 96         t[p].pos = min(t[p].pos,t[p].r - t[p].rlen + 1);
 97     if(t[p].tmax == d1)
 98         t[p].pos = min(t[p].pos,mid - t[lp].rlen + 1);
 99     if(t[p].tmax == t[lp].tmax)
100         t[p].pos = min(t[p].pos,t[lp].pos);
101     if(t[p].tmax == t[rp].tmax)
102         t[p].pos = min(t[p].pos,t[rp].pos);
103     
104     if(t[lp].cover == t[rp].cover)
105         t[p].cover = t[lp].cover;
106     else
107         t[p].cover = 0;
108 }
109 
110 void Query_tree(int d,int p,int l,int r){
111     if(t[p].tmax < d) return;
112     //available
113     int mid = getmid(l,r);
114     if(t[p].llen >= d){
115         ans = l;
116     }
117     else if(t[lp].tmax >= d){
118         Query_tree(d,lp,l,mid);
119     }
120     else if(t[lp].rlen + t[rp].llen >= d){
121         ans = mid - t[lp].rlen + 1;
122     }
123     else if(t[rp].tmax >= d){
124         Query_tree(d,rp,mid + 1,r);
125     }
126     else{
127         ans = t[p].pos;
128     }
129 }    
130 
131 int main(){
132     int a,b,c;
133     scanf("%d%d",&N,&M);
134     Build_tree(1,1,N);
135     while(M--){
136         scanf("%d%d",&a,&b);
137         if(a == 1){
138             ans = -1;
139             Query_tree(b,1,1,N);
140             if(ans == -1) printf("0\n");
141             else{
142                 Update_tree(ans,ans + b - 1,1,1,1,N);
143                 printf("%d\n",ans);
144             }
145         }
146         else{
147             scanf("%d",&c);
148             Update_tree(b,b + c - 1,-1,1,1,N);
149         }
150     }
151     return 0;
152 }

 

posted @ 2014-10-02 00:16  Naturain  阅读(194)  评论(0)    收藏  举报