【HDOJ】3397 Sequence operation

线段树的应用,很不错的一道题目。结点属性包括:
(1)n1:1的个数;
(2)c1:连续1的最大个数;
(3)c0:连续0的最大个数;
(4)lc1/lc0:从区间左边开始,连续1/0的最大个数;
(5)rc1/rc0:从区间右边开始,连续1/0的最大个数;
(6)set:置区间为0/1的标记;
(7)flip:0->1, 1->0的标记。
采用延迟更新。每当更新set时,flip就置为false;每当更新flip时,其实就是c1/c0, lc1/lc0, rc1/rc0的交换。
对于询问最长连续1,共包括3种情况:左子树的最长连续1,右子树的最长连续1,以及左子树rc1+右子树lc1(注意有效范围区间)。

  1 /* 3397 */
  2 #include <iostream>
  3 #include <string>
  4 #include <map>
  5 #include <queue>
  6 #include <set>
  7 #include <vector>
  8 #include <algorithm>
  9 #include <cstdio>
 10 #include <cmath>
 11 #include <cstring>
 12 #include <climits>
 13 #include <cctype>
 14 using namespace std;
 15
 16 #define MAXN 100005
 17 #define lson l, mid, rt<<1
 18 #define rson mid+1, r, rt<<1|1
 19
 20 typedef struct {
 21     int set;
 22     int n1;
 23     int c1, c0;
 24     int lc1, lc0, rc1, rc0;
 25     bool flip;
 26 } node_t;
 27
 28 node_t nd[MAXN<<2];
 29 int t, n, m, x;
 30 int op;
 31
 32 void maintance_set(int op, int len, int rt) {
 33     nd[rt].set = op;
 34     nd[rt].flip = false;
 35     if (op) {
 36         nd[rt].n1 = nd[rt].c1 = nd[rt].lc1 = nd[rt].rc1 = len;
 37         nd[rt].c0 = nd[rt].lc0 = nd[rt].rc0 = 0;
 38     } else {
 39         nd[rt].n1 = nd[rt].c1 = nd[rt].lc1 = nd[rt].rc1 = 0;
 40         nd[rt].c0 = nd[rt].lc0 = nd[rt].rc0 = len;
 41     }
 42 }
 43
 44 void maintance_flip(int len, int rt) {
 45     if (nd[rt].set >= 0)
 46         nd[rt].set = !nd[rt].set;
 47     else
 48         nd[rt].flip = !nd[rt].flip;
 49     nd[rt].n1 = len-nd[rt].n1;
 50     swap(nd[rt].c0, nd[rt].c1);
 51     swap(nd[rt].lc0, nd[rt].lc1);
 52     swap(nd[rt].rc0, nd[rt].rc1);
 53 }
 54
 55 void PushUp(int l, int r, int rt) {
 56     int lb = rt<<1;
 57     int rb = rt<<1|1;
 58     int mid = (l+r)>>1;
 59
 60     // update the number of 1
 61     nd[rt].n1 = nd[lb].n1 + nd[rb].n1;
 62     // update the longest continuous 1 and 0 in string
 63     nd[rt].c1 = max(
 64         max(nd[lb].c1, nd[rb].c1),
 65         nd[lb].rc1 + nd[rb].lc1
 66     );
 67     nd[rt].c0 = max(
 68         max(nd[lb].c0, nd[rb].c0),
 69         nd[lb].rc0 + nd[rb].lc0
 70     );
 71     // update the longest continuous 1/0 from left
 72     nd[rt].lc1 = nd[lb].lc1;
 73     nd[rt].lc0 = nd[lb].lc0;
 74     if (nd[lb].lc1 == mid-l+1)
 75         nd[rt].lc1 += nd[rb].lc1;
 76     if (nd[lb].lc0 == mid-l+1)
 77         nd[rt].lc0 += nd[rb].lc0;
 78     // update the longest continuous 1/0 from right
 79     nd[rt].rc1 = nd[rb].rc1;
 80     nd[rt].rc0 = nd[rb].rc0;
 81     if (nd[rb].rc1 == r-mid)
 82         nd[rt].rc1 += nd[lb].rc1;
 83     if (nd[rb].rc0 == r-mid)
 84         nd[rt].rc0 += nd[lb].rc0;
 85 }
 86
 87 void PushDown(int l, int r, int rt) {
 88     int lb = rt<<1;
 89     int rb = rt<<1|1;
 90     int mid = (l+r)>>1;
 91
 92     if (nd[rt].set >= 0) {
 93         // maintance_set lson & rson
 94         maintance_set(nd[rt].set, mid-l+1, lb);
 95         maintance_set(nd[rt].set, r-mid, rb);
 96         nd[rt].set = -1;
 97     }
 98     if (nd[rt].flip) {
 99         // maintance_flip lson & rson
100         maintance_flip(mid-l+1, lb);
101         maintance_flip(r-mid, rb);
102         nd[rt].flip = false;
103     }
104 }
105
106 void build(int l, int r, int rt) {
107     nd[rt].set = -1;
108     nd[rt].flip = false;
109     if (l == r) {
110         scanf("%d", &x);
111         nd[rt].n1 = nd[rt].c1 = nd[rt].lc1 = nd[rt].rc1 = x;
112         nd[rt].c0 = nd[rt].lc0 = nd[rt].rc0 = !x;
113         return ;
114     }
115     int mid = (l+r)>>1;
116     build(lson);
117     build(rson);
118     PushUp(l, r, rt);
119 }
120
121 // update to set [L, R] to op
122 void update1(int L, int R, int l, int r, int rt) {
123     if (L<=l && R>=r) {
124         maintance_set(op, r-l+1, rt);
125         return ;
126     }
127     int mid = (l+r)>>1;
128     PushDown(l, r, rt);
129     if (L <= mid)
130         update1(L, R, lson);
131     if (R > mid)
132         update1(L, R, rson);
133     PushUp(l, r, rt);
134 }
135
136 // update to flip [L, R] one
137 void update2(int L, int R, int l, int r, int rt) {
138     if (L<=l && R>=r) {
139         maintance_flip(r-l+1, rt);
140         return ;
141     }
142     int mid = (l+r)>>1;
143     PushDown(l, r, rt);
144     if (L <= mid)
145         update2(L, R, lson);
146     if (R > mid)
147         update2(L, R, rson);
148     PushUp(l, r, rt);
149 }
150
151 // query the sum of 1 in [L, R]
152 int query3(int L, int R, int l, int r, int rt) {
153     if (L<=l && R>=r)
154         return nd[rt].n1;
155     int mid = (l+r)>>1;
156     PushDown(l, r, rt);
157     int ret = 0;
158     if (L <= mid)
159         ret += query3(L, R, lson);
160     if (R > mid)
161         ret += query3(L, R, rson);
162     return ret;
163 }
164
165 // query the longest continous 1 in [L, R]
166 int query4(int L, int R, int l, int r, int rt) {
167     if (L<=l && R>=r)
168         return nd[rt].c1;
169     int mid = (l+r)>>1;
170     PushDown(l, r, rt);
171     int ret;
172     if (L > mid) {
173         return query4(L, R, rson);
174     } else if (R <= mid) {
175         return query4(L, R, lson);
176     } else {
177         ret = max(
178             query4(L, R, lson),
179             query4(L, R, rson)
180         );
181         int rc1 = nd[rt<<1].rc1;
182         int lc1 = nd[rt<<1|1].lc1;
183         if (rc1 > mid-L+1)
184             rc1 = mid-L+1;
185         if (lc1 > R-mid)
186             lc1 = R-mid;
187         ret = max(
188             rc1 + lc1,
189             ret
190         );
191     }
192     return ret;
193 }
194
195 int main() {
196     int i, j, k;
197     int a, b;
198
199     #ifndef ONLINE_JUDGE
200         freopen("data.in", "r", stdin);
201         freopen("data.out", "w", stdout);
202     #endif
203
204     scanf("%d", &t);
205     while (t--) {
206         scanf("%d %d", &n, &m);
207         build(1, n, 1);
208         while (m--) {
209             scanf("%d %d %d", &op, &a, &b);
210             ++a;
211             ++b;
212             if (op == 0) {
213                 update1(a, b, 1, n, 1);
214             } else if (op == 1) {
215                 update1(a, b, 1, n, 1);
216             } else if (op == 2) {
217                 update2(a, b, 1, n, 1);
218             } else if (op == 3) {
219                 k = query3(a, b, 1, n, 1);
220                 printf("%d\n", k);
221             } else {
222                 k = query4(a, b, 1, n, 1);
223                 printf("%d\n", k);
224             }
225         }
226     }
227
228     return 0;
229 }
时间: 2024-10-05 06:15:04

【HDOJ】3397 Sequence operation的相关文章

【线段树】HDU 3397 Sequence operation 区间合并

操作 Change operations: 0 a b change all characters into '0's in [a , b] 1 a b change all characters into '1's in [a , b] 2 a b change all '0's into '1's and change all '1's into '0's in [a, b] Output operations: 3 a b output the number of '1's in [a,

【HDOJ】1818 It&#39;s not a Bug, It&#39;s a Feature!

状态压缩+优先级bfs. 1 /* 1818 */ 2 #include <iostream> 3 #include <queue> 4 #include <cstdio> 5 #include <cstring> 6 #include <cstdlib> 7 #include <algorithm> 8 using namespace std; 9 10 #define MAXM 105 11 12 typedef struct {

HDU 3397 Sequence operation (线段树,成段更新,区间合并)

http://acm.hdu.edu.cn/showproblem.php?pid=3397 Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5801    Accepted Submission(s): 1713 Problem Description lxhgww got a sequence

HDU 3397 Sequence operation(线段树)

HDU 3397 Sequence operation 题目链接 题意:给定一个01序列,有5种操作 0 a b [a.b]区间置为0 1 a b [a,b]区间置为1 2 a b [a,b]区间0变成1,1变成0 3 a b 查询[a,b]区间1的个数 4 a b 查询[a,b]区间连续1最长的长度 思路:线段树线段合并.须要两个延迟标记一个置为01,一个翻转,然后因为4操作,须要记录左边最长0.1.右边最长0.1,区间最长0.1,然后区间合并去搞就可以 代码: #include <cstdi

【HDOJ】4956 Poor Hanamichi

基本数学题一道,看错位数,当成大数减做了,而且还把方向看反了.所求为最接近l的值. 1 #include <cstdio> 2 3 int f(__int64 x) { 4 int i, sum; 5 6 i = sum = 0; 7 while (x) { 8 if (i & 1) 9 sum -= x%10; 10 else 11 sum += x%10; 12 ++i; 13 x/=10; 14 } 15 return sum; 16 } 17 18 int main() { 1

【HDOJ】1099 Lottery

题意超难懂,实则一道概率论的题目.求P(n).P(n) = n*(1+1/2+1/3+1/4+...+1/n).结果如果可以除尽则表示为整数,否则表示为假分数. 1 #include <cstdio> 2 #include <cstring> 3 4 #define MAXN 25 5 6 __int64 buf[MAXN]; 7 8 __int64 gcd(__int64 a, __int64 b) { 9 if (b == 0) return a; 10 else return

【HDOJ】2844 Coins

完全背包. 1 #include <stdio.h> 2 #include <string.h> 3 4 int a[105], c[105]; 5 int n, m; 6 int dp[100005]; 7 8 int mymax(int a, int b) { 9 return a>b ? a:b; 10 } 11 12 void CompletePack(int c) { 13 int i; 14 15 for (i=c; i<=m; ++i) 16 dp[i]

【HDOJ】3509 Buge&#39;s Fibonacci Number Problem

快速矩阵幂,系数矩阵由多个二项分布组成.第1列是(0,(a+b)^k)第2列是(0,(a+b)^(k-1),0)第3列是(0,(a+b)^(k-2),0,0)以此类推. 1 /* 3509 */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #incl

【HDOJ】2424 Gary&#39;s Calculator

大数乘法加法,直接java A了. 1 import java.util.Scanner; 2 import java.math.BigInteger; 3 4 public class Main { 5 public static void main(String[] args) { 6 Scanner cin = new Scanner(System.in); 7 int n; 8 int i, j, k, tmp; 9 int top; 10 boolean flag; 11 int t