线段树懒标记好题 HDU4578
Posted Lorazepam
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树懒标记好题 HDU4578相关的知识,希望对你有一定的参考价值。
(1)"1 x y c",代表 把区间 [x,y] 上的值全部加c
(2)"2 x y c",代表 把区间 [x,y] 上的值全部乘以c
(3)"3 x y c" 代表 把区间 [x,y]上的值全部赋值为c
(4)"4 x y p" 代表 求区间 [x,y] 上值的p次方和1<=p<=3
维护sum1[], sum2[], sum3[]分别为一次方、二次方、三次方的和
因为P只有1到3,(x+c)^2=(x^2)+(2*x*c+c^2),即我们可以从一次方和的结果推出二次方的和的结果。同理,我们也可以根据一次方的和的结果,二次方和的结果推出三次方和的结果。这样,我们可以用几个懒标记去记录这几个操作。但是这题明白上面这点还是不够的,因为,这几种更新操作之间会相互影响,比如对一个区间进行操作3之后,那么操作1和2就失效了。因此在PushDown传递懒标记的时候,传递的顺序也是重要的。
1 #include <bits/stdc++.h> 2 #include <string.h> 3 #include <iostream> 4 #include <stdio.h> 5 #define pb push_back 6 #define fi first 7 #define se second 8 #define lson(r) (r<<1) 9 #define rson(r) ((r<<1)|1) 10 11 using namespace std; 12 13 typedef long long ll; 14 15 const int MAXN = 1e5+7; 16 const int MAXV = 507; 17 const int MAXE = 507; 18 const ll MOD = 10007; 19 ll sum1[MAXN << 2]; 20 ll sum2[MAXN << 2]; 21 ll sum3[MAXN << 2]; 22 ll addmark[MAXN << 2]; 23 ll setmark[MAXN << 2]; 24 ll mulmark[MAXN << 2]; 25 26 void pushDown(int root, int l, int r) 27 { 28 int num = (r-l+1); 29 ll numr = num >> 1; 30 ll numl = num - numr; 31 //思考了半天用-1还是不够优秀呀 只需要把另外优先级低的懒标记 标记的左右子即可 32 //修改了半天 哎哎哎 这道题目深入理解懒标记 33 if (setmark[root]) 34 { 35 ll setval = setmark[root]; 36 //cout << "set" << l << " " << r << " " << setmark[root] << endl; 37 sum1[lson(root)] = (numl*setval) % MOD; 38 sum1[rson(root)] = (numr*setval) % MOD; 39 sum2[lson(root)] = (numl*setval*setval) % MOD; 40 sum2[rson(root)] = (numr*setval*setval) % MOD; 41 sum3[lson(root)] = (numl*setval*setval*setval) % MOD; 42 sum3[rson(root)] = (numr*setval*setval*setval) % MOD; 43 setmark[lson(root)] = setval; 44 setmark[rson(root)] = setval; 45 addmark[lson(root)] = addmark[rson(root)] = 0; 46 mulmark[lson(root)] = mulmark[rson(root)] = 1; 47 setmark[root] = 0; 48 } 49 if (mulmark[root] != 1) 50 { 51 ll mulval = mulmark[root]; 52 sum1[lson(root)] = (sum1[lson(root)]*mulval) % MOD; 53 sum1[rson(root)] = (sum1[rson(root)]*mulval) % MOD; 54 sum2[lson(root)] = (sum2[lson(root)]*mulval*mulval) % MOD; 55 sum2[rson(root)] = (sum2[rson(root)]*mulval*mulval) % MOD; 56 sum3[lson(root)] = (sum3[lson(root)]*mulval*mulval*mulval) % MOD; 57 sum3[rson(root)] = (sum3[rson(root)]*mulval*mulval*mulval) % MOD; 58 mulmark[lson(root)] = (mulmark[lson(root)]*mulval) % MOD; 59 mulmark[rson(root)] = (mulmark[rson(root)]*mulval) % MOD; 60 addmark[lson(root)] = (addmark[lson(root)]*mulval) % MOD; 61 addmark[rson(root)] = (addmark[rson(root)]*mulval) % MOD; 62 mulmark[root] = 1; 63 } 64 if (addmark[root]) 65 { 66 ll addval = addmark[root]; 67 sum3[lson(root)] = ((sum3[lson(root)]+numl*addval*addval*addval)%MOD+(3*sum2[lson(root)]*addval+3*sum1[lson(root)]*addval*addval)%MOD)%MOD; 68 sum3[rson(root)] = ((sum3[rson(root)]+numr*addval*addval*addval)%MOD+(3*sum2[rson(root)]*addval+3*sum1[rson(root)]*addval*addval)%MOD)%MOD; 69 sum2[lson(root)] = (((sum2[lson(root)] + numl*addval*addval) % MOD) + (2*sum1[lson(root)]*addval)) % MOD; 70 sum2[rson(root)] = (((sum2[rson(root)] + numr*addval*addval) % MOD) + (2*sum1[rson(root)]*addval)) % MOD; 71 sum1[lson(root)] = (sum1[lson(root)] + numl * addval) % MOD; 72 sum1[rson(root)] = (sum1[rson(root)] + numr * addval) % MOD; 73 addmark[lson(root)] = (addmark[lson(root)] + addval) % MOD; 74 addmark[rson(root)] = (addmark[rson(root)] + addval) % MOD; 75 addmark[root] = 0; 76 } 77 } 78 void update(int root, int l, int r, int ul, int ur, int mathod, ll val) 79 { 80 if (l > ur || r < ul) return ; 81 if (l >= ul && r <= ur) 82 { 83 ll num = r-l+1; 84 if (mathod == 1) 85 { 86 //cout << l << " " << r << " " << val << endl; 87 setmark[root] = val%MOD; 88 addmark[root] = 0; 89 mulmark[root] = 1; 90 sum1[root] = (num*val) % MOD; 91 sum2[root] = (num*val*val) % MOD; 92 sum3[root] = (num*val*val*val) % MOD; 93 } 94 else if (mathod == 2) 95 { 96 mulmark[root] = (mulmark[root]*val)%MOD; 97 addmark[root] = (val*addmark[root])%MOD; 98 sum1[root] = (sum1[root]*val) % MOD; 99 sum2[root] = (sum2[root]*val*val) % MOD; 100 sum3[root] = (sum3[root]*val*val*val) % MOD; 101 } 102 else if (mathod == 3) 103 { 104 105 //cout << l << " " << r << " " << sum1[root] << endl; 106 addmark[root] = (addmark[root]+val)%MOD; 107 sum3[root] = ((sum3[root]+num*val*val*val)%MOD+(3*sum2[root]*val+3*sum1[root]*val*val)%MOD)%MOD; 108 sum2[root] = ((sum2[root] + num*val*val) % MOD + (2*sum1[root]*val)) % MOD; 109 sum1[root] = (sum1[root] + num * val) % MOD; 110 //cout << l << " " << r << " " << sum1[root] << endl; 111 } 112 return ; 113 } 114 pushDown(root, l, r); 115 int mid = (l+r) >> 1; 116 if (ul <= mid) update(lson(root), l, mid, ul, ur, mathod, val); 117 if (ur > mid) update(rson(root), mid+1, r, ul, ur, mathod, val); 118 sum1[root] = (sum1[lson(root)] + sum1[rson(root)]) % MOD; 119 sum2[root] = (sum2[lson(root)] + sum2[rson(root)]) % MOD; 120 sum3[root] = (sum3[lson(root)] + sum3[rson(root)]) % MOD; 121 //cout << l << " " << r << " " << sum1[root] << endl; 122 } 123 124 int cnt = 0; 125 ll query(int root, int l, int r, int ql, int qr, int p) 126 { 127 // cout << l << " " << r << endl; 128 if (l > qr || r < ql) return 0; 129 if (l >= ql && r <= qr) 130 { 131 if (p == 1) return sum1[root]; 132 else if (p == 2) return sum2[root]; 133 else if (p == 3) return sum3[root]; 134 } 135 pushDown(root, l, r); 136 int mid = (l+r) >> 1; 137 ll res = 0; 138 if (ql <= mid) res = (res + query(lson(root), l, mid, ql, qr, p)) % MOD; 139 if (qr >= mid+1) res = (res + query(rson(root), mid+1, r, ql, qr, p)) % MOD; 140 return res; 141 } 142 int n, m; 143 int main() 144 { 145 // freopen("in.txt", "r", stdin); 146 while (~scanf("%d%d", &n, &m)) 147 { 148 for(int i = 0; i < MAXN << 2; i++) mulmark[i] = 1; 149 if (!n && !m) break; 150 memset(addmark, 0, sizeof(addmark)); 151 //memset(mulmark, 1, sizeof(mulmark)); 152 memset(setmark, 0, sizeof(setmark)); 153 memset(sum1, 0, sizeof(sum1)); 154 memset(sum2, 0, sizeof(sum2)); 155 memset(sum3, 0, sizeof(sum3)); 156 for (int i = 0; i < m; i++) 157 { 158 int op, l, r, c; 159 scanf("%d%d%d%d", &op, &l, &r, &c); 160 if (op == 1) 161 { 162 update(1, 1, n, l, r, 3, c); 163 } 164 else if (op == 2) 165 { 166 update(1, 1, n, l, r, 2, c); 167 } 168 else if (op == 3) 169 { 170 update(1, 1, n, l, r, 1, c); 171 } 172 else 173 { 174 ll ans = query(1, 1, n, l, r, c); 175 cout << ans << endl; 176 } 177 } 178 } 179 return 0; 180 }
以上是关于线段树懒标记好题 HDU4578的主要内容,如果未能解决你的问题,请参考以下文章
HDU - 4578 Transformation(线段树区间修改)