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 }

 

posted @ 2014-09-25 23:16  Naturain  阅读(131)  评论(0)    收藏  举报