HDU 3397 Sequence operation 线段树

再做一道线段树。

http://acm.hdu.edu.cn/showproblem.php?pid=3397

这题还是很有意义的,其特殊之处在于操作2和操作4.

操作2是0变1,1变0,这样在pushdown的时候就不能简单覆盖下去,因为如果孩子节点有操作没有完成,会导致结果错误。但是又不能遇到操作2就把子节点也pushdown,这样会超时。。。需要想点办法。。。所以观察一下操作2的效果,可以得出如下结论:

当字节点操作未做操作为1时,将操作2pushdown下来等同于将字节点进行0操作

同理,字节点未做操作为0时,等同于1操作;当字节点未做操作为2时,等同于什么也不做;字节点没有未做操作时,直接覆盖即可。

这样就解决了操作2的pushdown问题。

接下来解决操作4的问题:求最长的连续1的长度。

这个问题和以前做过的“内存分配”问题类似,最长连续1的来源有三种:

左子树,右子树或跨左右子树中间的一段。

因此,在线段树节点中还需要记录该节点包含最左边的连续1的长度/包含最右边的连续1的长度。

为了操作方便,在线段树节点上还记录了对应得0的个数,这样在进行操作2时只需简单进行一下值交换即可。

另外还需要注意的一点是节点上包含的连续1长度可能会大于查询的范围,此处应注意一下。

 

  1 //5931624    2012-05-12 10:24:25    Accepted    3397    953MS    10944K    5137 B    C++    nkhelloworld
  2 //5931486    2012-05-12 10:05:33    Accepted    3397    1578MS    11208K    6639 B    G++    nkhelloworld
  3 #include <cstdio>
  4 #include <iostream>
  5 #include <cstring>
  6 using namespace std;
  7 
  8 #define MAXN 110000
  9 int n,m;
 10 int a[MAXN];
 11 
 12 struct SEGTREE
 13 {
 14     int l,r,num,len1,len0,lsublen1,rsublen1,lsublen0,rsublen0,op;
 15 }tree[MAXN*4];
 16 
 17 void refresh(int root)
 18 {
 19     tree[root].num = tree[root<<1].num + tree[root<<1|1].num;
 20 
 21     tree[root].len1 = max(tree[root<<1].len1, max(tree[root<<1|1].len1,
 22                 tree[root<<1].rsublen1+tree[root<<1|1].lsublen1));
 23     tree[root].len0 = max(tree[root<<1].len0, max(tree[root<<1|1].len0,
 24                 tree[root<<1].rsublen0 + tree[root<<1|1].lsublen0));
 25 
 26     tree[root].lsublen1 = tree[root<<1].lsublen1;
 27     if(tree[root].lsublen1 == tree[root<<1].r - tree[root<<1].l + 1)
 28         tree[root].lsublen1 += tree[root<<1|1].lsublen1;
 29 
 30     tree[root].rsublen1 = tree[root<<1|1].rsublen1;
 31     if(tree[root].rsublen1 == tree[root<<1|1].r - tree[root<<1|1].l + 1)
 32         tree[root].rsublen1 += tree[root<<1].rsublen1;
 33 
 34     tree[root].lsublen0 = tree[root<<1].lsublen0;
 35     if(tree[root].lsublen0 == tree[root<<1].r - tree[root<<1].l + 1)
 36         tree[root].lsublen0 += tree[root<<1|1].lsublen0;
 37 
 38     tree[root].rsublen0 = tree[root<<1|1].rsublen0;
 39     if(tree[root].rsublen0 == tree[root<<1|1].r - tree[root<<1|1].l + 1)
 40         tree[root].rsublen0 += tree[root<<1].rsublen0;
 41 }
 42 
 43 void buildsegtree(int root,int l,int r)
 44 {
 45     tree[root].l = l;    tree[root].r = r;
 46     tree[root].op = -1;
 47     if(l == r)
 48     {
 49         tree[root].num = a[l];
 50         tree[root].len1 = tree[root].lsublen1 
 51             = tree[root].rsublen1 = a[l]?1:0;
 52         tree[root].len0 = tree[root].lsublen0 
 53             = tree[root].rsublen0 = a[l]?0:1;
 54         return ;
 55     }
 56     int mid = (l+r)>>1;
 57     buildsegtree(root<<1,l,mid);
 58     buildsegtree(root<<1|1,mid+1,r);
 59     refresh(root);
 60 }
 61 
 62 void pushdown(int root)
 63 {
 64     if(tree[root].op == -1)    return ;
 65     if(tree[root].l != tree[root].r)
 66     {
 67         if(tree[root].op == 2)
 68         {
 69             switch(tree[root<<1].op)
 70             {
 71                 case -1:    tree[root<<1].op = 2;    break;
 72                 case 0:        tree[root<<1].op = 1;    break;
 73                 case 1:        tree[root<<1].op = 0;    break;
 74                 case 2:        tree[root<<1].op = -1;    break;
 75             }
 76             switch(tree[root<<1|1].op)
 77             {
 78                 case -1:    tree[root<<1|1].op = 2;    break;
 79                 case 0:        tree[root<<1|1].op = 1;    break;
 80                 case 1:        tree[root<<1|1].op = 0;    break;
 81                 case 2:        tree[root<<1|1].op = -1;    break;
 82             }
 83 
 84         }
 85         else
 86             tree[root<<1].op = tree[root<<1|1].op = tree[root].op;
 87     }
 88     if(tree[root].op == 0)
 89     {
 90         tree[root].num
 91             = tree[root].len1
 92             = tree[root].lsublen1
 93             = tree[root].rsublen1
 94             = 0;
 95         tree[root].len0
 96             = tree[root].lsublen0
 97             = tree[root].rsublen0
 98             = tree[root].r - tree[root].l + 1;
 99     }
100     else if(tree[root].op == 1)
101     {
102         tree[root].num
103             = tree[root].len1
104             = tree[root].lsublen1
105             = tree[root].rsublen1
106             = tree[root].r - tree[root].l + 1;
107         tree[root].len0
108             = tree[root].lsublen0
109             = tree[root].rsublen0
110             = 0;
111     }
112     else
113     {
114         tree[root].num = tree[root].r - tree[root].l + 1 - tree[root].num;
115         swap(tree[root].len0,tree[root].len1);
116         swap(tree[root].lsublen1,tree[root].lsublen0);
117         swap(tree[root].rsublen1,tree[root].rsublen0);
118     }
119     tree[root].op = -1;
120 }
121 
122 int query_num(int root,int l,int r)
123 {
124     pushdown(root);
125     if(tree[root].l == l && tree[root].r == r)
126         return tree[root].num;
127     int mid = (tree[root].l + tree[root].r)>>1;
128     if(r <= mid)
129         return query_num(root<<1,l,r);
130     else if(l > mid)
131         return query_num(root<<1|1,l,r);
132     else
133         return query_num(root<<1,l,mid) + query_num(root<<1|1,mid+1,r);
134 }
135 
136 int query_lenth(int root,int l,int r)
137 {
138     pushdown(root);
139     if(tree[root].l == l && tree[root].r == r)
140         return tree[root].len1;
141     int mid = (tree[root].l + tree[root].r)>>1;
142     if(r <= mid)
143         return query_lenth(root<<1,l,r);
144     else if(l > mid)
145         return query_lenth(root<<1|1,l,r);
146     else
147     {
148         pushdown(root<<1);
149         pushdown(root<<1|1);
150         int ret = max(query_lenth(root<<1,l,mid),
151                 query_lenth(root<<1|1,mid+1,r));
152         int lchild1 = tree[root<<1].rsublen1;
153         if(lchild1 > mid-l+1)    lchild1 = mid-l+1;
154         int rchild1 = tree[root<<1|1].lsublen1;
155         if(rchild1 > r-mid)        rchild1 = r-mid;
156         return max(ret,lchild1+rchild1);
157     }
158 
159 }
160 
161 void update(int root,int l,int r,int op)
162 {
163     pushdown(root);
164     if(tree[root].l == l && tree[root].r == r)
165     {
166         tree[root].op = op;
167         return ;
168     }
169     int mid = (tree[root].l + tree[root].r)>>1;
170     if(r<=mid)
171         update(root<<1,l,r,op);
172     else if(l > mid)
173         update(root<<1|1,l,r,op);
174     else
175     {
176         update(root<<1,l,mid,op);
177         update(root<<1|1,mid+1,r,op);
178     }
179     pushdown(root<<1);
180     pushdown(root<<1|1);
181     refresh(root);
182 }
183 
184 int main()
185 {
186     int i,j,totcase;
187     scanf("%d",&totcase);
188     while(totcase--)
189     {
190         scanf("%d%d",&n,&m);
191         for(i=1;i<=n;i++)
192         {
193             scanf("%d",&a[i]);
194         }
195         buildsegtree(1,1,n);
196         int op,a,b;
197         while(m--)
198         {
199             scanf("%d%d%d",&op,&a,&b);
200             a++;    b++;
201             if(op<=2)
202             {
203                 update(1,a,b,op);
204             }
205             else if(op==3)
206             {
207                 printf("%d\n",query_num(1,a,b));
208             }
209             else
210                 printf("%d\n",query_lenth(1,a,b));
211         }
212     }
213     return 0;
214 }

转载于:https://www.cnblogs.com/nkhelloworld/archive/2012/05/12/2497071.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值