题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902
题目大意:给你一串序列an,有两种操作,操作1:将区间l-r内的所有值替换成x,操作2:将区间l-r内大于x的数替换成x和a[i]的最大公约数;
思路:本题需要用lazy标记剪枝,操作一需要将区间内的所有值都替换,这是很简单的区间修改,用lazy标记存一下需要替换的值,另外本题需要用节点来表示此节点的左右儿子节点的最大值,这样做的目的是便于操作2中搜寻大于x的数值,在操作2中如果不加剪枝处理,那么只能单纯递归到l==r时修改节点值,这样做的话会TLE,那么此时会考虑到,如果在某个节点下的所有儿子节点的值都相等的话,就不需要递归到l==r时修改,只需要在当前节点修改一下节点的值,并用lazy存一下后序节点需要同样修改的x值,如果要实现这个操作的话,我们需要再引入一个标记laz(表示此节点下所有值都相同),如果某个节点的左右儿子节点的值都相等并且左右儿子的laz标记都是1的话,此节点的laz才是1,(注意:本题中的节点值表示的是左右儿子的最大值,最大值相同不代表此节点下的所有儿子值都相同,因为这个坑,我wa了一发),所以需要将叶子节点的laz都设为1,PushUp的时候求每个节点的laz值,操作2的时候,碰到节点laz值为1的直接修改整个区间就ok了。
AC代码:
1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 #include<cmath>
5 #include<cstring>
6 #define ll long long
7 using namespace std;
8 const int MAXN = 100010;
9
10 int A[MAXN];
11 int lazy[MAXN << 2];
12 int laz[MAXN << 2];
13 int Sum[MAXN << 2];
14
15 int gcd(int a, int b)
16 {
17 if (b > a) return gcd(b, a);
18 int remind = a % b;
19 if (remind == 0) return b;
20 else return gcd(b, remind);
21 }
22
23
24 void PushUp(int rt) {
25 Sum[rt] = max(Sum[rt << 1], Sum[rt << 1 | 1]);
26 if (Sum[rt << 1] == Sum[rt << 1 | 1] && (laz[rt << 1] & laz[rt << 1 | 1])) {
27 laz[rt] = 1;
28 }
29 else laz[rt] = 0;
30 }
31 void Build(int l, int r, int rt) {
32 lazy[rt] = -1;
33 laz[rt] = 0;
34 if (l == r) {
35 laz[rt] = 1;
36 Sum[rt] = A[l];
37 return;
38 }
39 int m = (l + r) >> 1;
40 Build(l, m, rt << 1);
41 Build(m + 1, r, rt << 1 | 1);
42 //PushUp(rt);
43 }
44 //void PointUpdate(int L, int C, int l, int r, int rt) {
45 // if (l == r) {
46 // A[l] += C;
47 // Sum[rt] += C;
48 // lazy[rt] = 0;
49 // return;
50 // }
51 // int m = (l + r) >> 1;
52 // if (L <= m) PointUpdate(L, C, l, m, rt << 1);
53 // else PointUpdate(L, C, m + 1, r, rt << 1 | 1);
54 // //PushUp(rt);
55 //}
56 void PushDown(int rt, int ln, int rn) {
57 if (lazy[rt] != -1) {
58 lazy[rt << 1] = lazy[rt << 1 | 1] = lazy[rt];
59 Sum[rt << 1] = Sum[rt << 1 | 1] = lazy[rt];
60 lazy[rt] = -1;
61 }
62 }
63 void QjUpdate1(int L, int R, int C, int l, int r, int rt) {
64
65 //if (Sum[rt] == r - l + 1) return;
66 if (L <= l && r <= R) {
67 lazy[rt] = C;
68 Sum[rt] = C;
69 /*if (l == r) {
70 A[l] = C;
71 }*/
72 return;
73 }
74 int m = (l + r) >> 1;
75 PushDown(rt, m - l + 1, r - m);
76 if (m >= L) QjUpdate1(L, R, C, l, m, rt << 1);
77 if (m < R) QjUpdate1(L, R, C, m + 1, r, rt << 1 | 1);
78 PushUp(rt);
79 }
80 void QjUpdate2(int L, int R, int C, int l, int r, int rt) {
81
82 //if (Sum[rt] == r - l + 1) return;
83 if (L <= l && r <= R && laz[rt]) {
84 int p = gcd(Sum[rt], C);
85 //A[l] = p;
86 Sum[rt] = p;
87 lazy[rt] = p;
88 return;
89 }
90 //if (l == r) {
91 // //lazy[rt] = C;
92 // int p = gcd(Sum[rt], C);
93 // //A[l] = p;
94 // Sum[rt] = p;
95 // return;
96 //}
97 int m = (l + r) >> 1;
98 PushDown(rt, m - l + 1, r - m);
99 if (Sum[rt << 1] > C && L <= m) QjUpdate2(L, R, C, l, m, rt << 1);
100 if (Sum[rt << 1 | 1] > C && R > m) QjUpdate2(L, R, C, m + 1, r, rt << 1 | 1);
101 PushUp(rt);
102 }
103 //ll Query(int L, int R, int l, int r, int rt) {
104 // if (l >= L && r <= R) {
105 // return Sum[rt];
106 // }
107 // int m = (l + r) >> 1;
108 // //PushDown(rt, m - l + 1, r - m);
109 // ll ANS = 0;
110 // if (m >= L) ANS += Query(L, R, l, m, rt << 1);
111 // if (m < R) ANS += Query(L, R, m + 1, r, rt << 1 | 1);
112 // return ANS;
113 //}
114
115 void out(int l, int r, int rt) {
116
117 if (l == r) {
118 //cout << Sum[rt] << " ";
119 printf("%d ", Sum[rt]);
120 return;
121 }
122 //if (!lazy[rt]) return;
123 int m = (l + r) >> 1;
124 PushDown(rt, m - l + 1, r - m);
125 out(l, m, rt << 1);
126 out(m + 1, r, rt << 1 | 1);
127 PushUp(rt);
128 }
129
130 int main() {
131
132 /*ios::sync_with_stdio(false);
133 cin.tie(0);*/
134
135 int T;
136 scanf("%d", &T);
137 while (T--) {
138 int n, m;
139 scanf("%d", &n);
140 for (int i = 1; i <= n; i++) {
141 //cin >> A[i];
142 scanf("%d", &A[i]);
143 }
144 Build(1, n, 1);
145 scanf("%d", &m);
146 for (int i = 1; i <= m; i++) {
147 int op, x, y, val;
148 scanf("%d", &op);
149 if (op == 1) {
150 scanf("%d %d %d", &x, &y, &val);
151 QjUpdate1(x, y, val, 1, n, 1);
152 /*out(1, n, 1);
153 cout << "\n";*/
154 }
155 else {
156 scanf("%d %d %d", &x, &y, &val);
157 if (x == 1 && y == 8) {
158 QjUpdate2(x, y, val, 1, n, 1);
159 continue;
160 }
161 QjUpdate2(x, y, val, 1, n, 1);
162 /*out(1, n, 1);
163 cout << "\n";*/
164 }
165 }
166 out(1, n, 1);
167 putchar('\n');
168 }
169
170 return 0;
171 }