线段树懒标记好题 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的主要内容,如果未能解决你的问题,请参考以下文章

hdu4578 (多标记线段树)

HDU - 4578 Transformation(线段树区间修改)

HDU 4578(线段树

[HDOJ4578]Transformation(线段树,多延迟标记)

hdu 4578 Transformation 线段树

HDU 4578 线段树玄学算法?