Poj--1823(线段树,区间更新)
2014-09-25 23:05:10
思路:这题上课的时候琢磨了一下,然后敲出来发现不对。。还是太弱TAT。参考了别人的博客。
几个关键点:(1)这题融入了区间设置操作,即区间set,要用到push_down。然后我们发现并不是所有的节点都可以push_down。
(2)每个节点有个cover值,1:全占 ,-1:全空,0:非全空。这个非常关键。
(3)在Update操作里,能push_down的就push_down,不能push_down的节点可以证明在之前已经push_down了,也就是说其子节点已经有信息了。那么就不用往下传了,然后在递归完子节点后,要更新父节点。
1 /************************************************************************* 2 > File Name: seg.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Thu 25 Sep 2014 08:13:23 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 typedef long long ll; 18 #define lpos pos << 1 19 #define rpos pos << 1 | 1 20 const int INF = 1 << 29; 21 const int maxn = 16010; 22 23 struct node{ 24 int l,r; 25 int cover; //1 : all occupied , -1 : all empty , 0 : mid state 26 int plen,slen,len; 27 }a[maxn << 2]; 28 29 int aa,bb; 30 31 void Build_tree(int pos,int l,int r){ 32 a[pos].l = l; 33 a[pos].r = r; 34 a[pos].cover = -1; 35 a[pos].plen = a[pos].slen = a[pos].len = r - l + 1; 36 if(l == r) 37 return; 38 int mid = l + (r - l) / 2; 39 Build_tree(lpos,l,mid); 40 Build_tree(rpos,mid + 1,r); 41 //printf("a[%d] , l:%d , r:%d , cover:%d , plen:%d , slen:%d, len:%d\n", 42 // pos,a[pos].l,a[pos].r,a[pos].cover,a[pos].plen,a[pos].slen,a[pos].len); 43 } 44 45 void Push_down(int pos,int c){ 46 a[lpos].cover = c; 47 a[rpos].cover = c; 48 a[pos].cover = 0; 49 if(c == 1){ 50 a[lpos].plen = a[lpos].slen = a[lpos].len = 0; 51 a[rpos].plen = a[rpos].slen = a[rpos].len = 0; 52 } 53 else{ 54 int d = a[lpos].r - a[lpos].l + 1; 55 a[lpos].plen = a[lpos].slen = a[lpos].len = d; 56 d = a[rpos].r - a[rpos].l + 1; 57 a[rpos].plen = a[rpos].slen = a[rpos].len = d; 58 } 59 } 60 61 void Update(int pos,int l,int r,int t){ 62 if(aa <= l && r <= bb){ 63 a[pos].cover = t; 64 if(t == 1) 65 a[pos].plen = a[pos].slen = a[pos].len = 0; 66 else 67 a[pos].plen = a[pos].slen = a[pos].len = a[pos].r - a[pos].l + 1; 68 return; 69 } 70 if(a[pos].cover == t) return; //cover 为0意味着子节点不是全空或全占 71 else if(a[pos].cover == -t) Push_down(pos,-t); //全空 or 全占 72 //explain : 如果是非全空,pushdown操作反而不好进行,而非全空节点在之前一定pushdown过 73 int mid = l + (r - l) / 2; 74 if(aa <= mid) Update(lpos,l,mid,t); 75 if(bb > mid) Update(rpos,mid + 1,r,t); 76 //Maintain 77 a[pos].plen = a[lpos].plen; 78 if(a[lpos].cover == -1) 79 a[pos].plen += a[rpos].plen; 80 a[pos].slen = a[rpos].slen; 81 if(a[rpos].cover == -1) 82 a[pos].slen += a[lpos].slen; 83 int d1 = max(a[lpos].len,a[rpos].len); 84 int d2 = a[lpos].slen + a[rpos].plen; 85 int d3 = max(a[pos].plen,a[pos].slen); 86 a[pos].len = max(d1,max(d2,d3)); 87 if(a[lpos].cover == a[rpos].cover) 88 a[pos].cover = a[lpos].cover; 89 else 90 a[pos].cover = 0; 91 } 92 93 int main(){ 94 int N,P,c; 95 scanf("%d%d",&N,&P); 96 Build_tree(1,1,N); 97 while(P--){ 98 scanf("%d",&c); 99 if(c == 3){ 100 printf("%d\n",a[1].len); 101 } 102 else{ 103 scanf("%d%d",&aa,&bb); 104 bb = aa + bb - 1; 105 Update(1,1,N,(c == 1 ? 1 : -1)); 106 } 107 } 108 return 0; 109 }

浙公网安备 33010602011771号