标签:
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4578
----------------------------------------------------------------------------------
一道操作比较复杂的线段树的题目
强烈建议线段树写得比较少的同学把操作$1,2,3$一个一个地加上去
直接写三个操作思路可能比较乱
这题是求区间$1$到$3$次方的和 对于1操作 需要推导下如何更新
假设区间长度为$len 1,2,3 $次方的和分别为$ sum1$ $sum2$ $sum3$
更新后为$ sum1‘$ $sum2‘$ $sum3‘ $那么
$sum1‘ = sum1 + c * len$
$sum2‘ = sum2 + sum1 * c * 2 + c * c * len$
$sum3‘ = sum3 + sum2 * c * 3 + sum1 * c * c * 3 + c * c * c * len$
其他部分都还好 就是要耐心一点去分析 代码量只有$2K+$
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 const int N = 100010, mod = 10007; 7 int sum[3][N << 2], flag[3][N << 2]; 8 int n, m; 9 void update(int x, int L, int R, int tl, int tr, int o, int c); 10 void build(int x, int tl, int tr) 11 { 12 sum[0][x] = sum[1][x] = sum[2][x] = 0; 13 flag[0][x] = flag[2][x] = 0; 14 flag[1][x] = 1; 15 if(tl == tr) 16 return; 17 int mid = (tl + tr) >> 1; 18 build(x << 1, tl, mid); 19 build(x << 1 | 1, mid + 1, tr); 20 } 21 void pushdown(int x, int tl, int tr) 22 { 23 int mid = (tl + tr) >> 1; 24 for(int i = 2; i >= 0; --i) 25 if(flag[i][x] && !(i == 1 && flag[i][x] == 1)) 26 { 27 update(x << 1, tl, mid, tl, mid, i, flag[i][x]); 28 update(x << 1 | 1, mid + 1, tr, mid + 1, tr, i, flag[i][x]); 29 flag[i][x] = (i == 1 ? 1 : 0); 30 } 31 } 32 void update(int x, int L, int R, int tl, int tr, int o, int c) 33 { 34 int mid = (tl + tr) >> 1; 35 if(L <= tl && tr <= R) 36 { 37 if(o == 0) 38 { 39 flag[0][x] = (flag[0][x] + c) % mod; 40 sum[2][x] = (sum[2][x] + sum[1][x] * c * 3 % mod 41 + sum[0][x] * c % mod * c * 3 % mod + c * c % mod * c % mod * 42 (tr - tl + 1) % mod) % mod; 43 sum[1][x] = (sum[1][x] + sum[0][x] * c * 2 % mod + c * c % mod * 44 (tr - tl + 1) % mod) % mod; 45 sum[0][x] = (sum[0][x] + c * (tr - tl + 1) % mod) % mod; 46 } 47 else if(o == 1) 48 { 49 flag[0][x] = flag[0][x] * c % mod; 50 flag[1][x] = flag[1][x] * c % mod; 51 sum[0][x] = sum[0][x] * c % mod; 52 sum[1][x] = sum[1][x] * c % mod * c % mod; 53 sum[2][x] = sum[2][x] * c % mod * c % mod * c % mod; 54 } 55 else 56 { 57 flag[0][x] = 0; 58 flag[1][x] = 1; 59 flag[2][x] = c; 60 sum[0][x] = (tr - tl + 1) * c % mod; 61 sum[1][x] = (tr - tl + 1) * c % mod * c % mod; 62 sum[2][x] = (tr - tl + 1) * c % mod * c % mod * c % mod; 63 } 64 return; 65 } 66 pushdown(x, tl, tr); 67 if(L <= mid) 68 update(x << 1, L, R, tl, mid, o, c); 69 if(mid < R) 70 update(x << 1 | 1, L, R, mid + 1, tr, o, c); 71 for(int i = 0; i < 3; ++i) 72 sum[i][x] = (sum[i][x << 1] + sum[i][x << 1 | 1]) % mod; 73 } 74 int query(int x, int L, int R, int tl, int tr, int p) 75 { 76 if(L <= tl && tr <= R) 77 return sum[p][x]; 78 pushdown(x, tl, tr); 79 int mid = (tl + tr) >> 1, re= 0; 80 if(L <= mid) 81 re += query(x << 1, L, R, tl, mid, p); 82 if(mid < R) 83 re += query(x << 1 | 1, L, R, mid + 1, tr, p); 84 return re % mod; 85 } 86 int main() 87 { 88 while(scanf("%d%d", &n, &m),n) 89 { 90 build(1, 1, n); 91 int o, x, y, c; 92 while(m--) 93 { 94 scanf("%d%d%d%d", &o, &x, &y, &c); 95 if(o != 4) 96 update(1, x, y, 1, n, o - 1, c); 97 else 98 printf("%d\n", query(1, x, y, 1, n, c - 1)); 99 } 100 } 101 return 0; 102 }
标签:
原文地址:http://www.cnblogs.com/sagitta/p/5183988.html