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 }

浙公网安备 33010602011771号