http://acm.hdu.edu.cn/showproblem.php?pid=4578
题意:
含n个数字的的数列a各数字初值均为0,对其进行m次操作,每次操作可为下列之一:
1 x y c:ax到ay间的数字(含边界)均增加c
2 x y c:ax到ay间的数字(含边界)均乘以c
3 x y c:ax到ay间的数字(含边界)均变为c
4 x y p:输出ax到ay间的数字(含边界)的p次方之和
对于每个操作4,输出答案模10007
数据组数<=10。
1<=n,m<=1e5,1<=x<=y<=n,1<=c<=1e4,1<=p<=3
输入 0 0结束
解法:
有特意限制p就是水题了
假如p = 1那么显然就是普通的线段树
当p = 2或者p = 3的时候,第2、3种操作依然比较好处理
而对于第一种,我们列个求和公式就能发现更新其实很方便的
线段树里s[i]代表该线段覆覆盖元素的 i 次方之和
更新很简单(自己列求和公式想不出来就参照代码里pushdown函数吧
实现:
脑抽了没有线段树没有开s数组而是直接申请了三个变量s1,s2,s3
实际证明完全是给自己找麻烦
手残居然磨磨唧唧写了1h...
还WA了...算了明天再改吧晚安
1 #include <cstdio> 2 3 #define lc (o << 1) 4 #define rc (o << 1 | 1) 5 6 typedef long long ll; 7 8 const int Mod = 10007; 9 const int maxn = 100010; 10 11 struct node { 12 ll s1, s2, s3; 13 ll laza, lazm, lazc; 14 void clear() { 15 s1 = s2 = s3 = 0; 16 laza = lazc = 0; 17 lazm = 1; 18 } 19 }tr[maxn << 2]; 20 21 ll z; 22 int Case, n, m, x, y, op; 23 24 void pushup(int o) { 25 tr[o].s1 = tr[lc].s1 + tr[rc].s1; 26 tr[o].s2 = tr[lc].s2 + tr[rc].s2; 27 tr[o].s3 = tr[lc].s3 + tr[rc].s3; 28 } 29 30 void pushdown(int o, int l, int r) { 31 int mid = (l + r) >> 1; 32 if(tr[o].lazc) { 33 tr[lc].s3 = tr[o].lazc * tr[o].lazc * tr[o].lazc * (mid - l + 1) % Mod; 34 tr[rc].s3 = tr[o].lazc * tr[o].lazc * tr[o].lazc * (r - mid) % Mod; 35 tr[lc].s2 = tr[o].lazc * tr[o].lazc * (mid - l + 1) % Mod; 36 tr[rc].s2 = tr[o].lazc * tr[o].lazc * (r - mid) % Mod; 37 tr[lc].s1 = tr[o].lazc * (mid - l + 1) % Mod; 38 tr[rc].s1 = tr[o].lazc * (r - mid) % Mod; 39 tr[lc].lazc = tr[rc].lazc = tr[o].lazc; 40 tr[lc].laza = tr[rc].laza = 0; 41 tr[lc].lazm = tr[rc].lazm = 0; 42 tr[o].lazc = 0; 43 } 44 if(tr[o].laza) { 45 tr[lc].s3 = (tr[lc].s3 + tr[o].laza * tr[lc].s2 * 3 + tr[o].laza * tr[o].laza * tr[lc].s1 * 3 + tr[o].laza * tr[o].laza * tr[o].laza * (mid - l + 1)) % Mod; 46 tr[rc].s3 = (tr[rc].s3 + tr[o].laza * tr[rc].s2 * 3 + tr[o].laza * tr[o].laza * tr[rc].s1 * 3 + tr[o].laza * tr[o].laza * tr[o].laza * (r - mid)) % Mod; 47 tr[lc].s2 = (tr[lc].s2 + tr[o].laza * tr[lc].s1 * 2 + tr[o].laza * tr[o].laza * (mid - l + 1)) % Mod; 48 tr[rc].s2 = (tr[rc].s2 + tr[o].laza * tr[rc].s1 * 2 + tr[o].laza * tr[o].laza * (r - mid)) % Mod; 49 tr[lc].s1 = (tr[lc].s1 + tr[o].laza * (mid - l + 1)) % Mod; 50 tr[rc].s1 = (tr[rc].s1 + tr[o].laza * (r - mid)) % Mod; 51 tr[lc].laza = (tr[lc].laza + tr[o].laza) % Mod; 52 tr[rc].laza = (tr[rc].laza + tr[o].laza) % Mod; 53 tr[o].laza = 0; 54 } 55 if(tr[o].lazm != 1) { 56 tr[lc].s3 = (tr[lc].s3 * tr[o].lazm * tr[o].lazm * tr[o].lazm) % Mod; 57 tr[rc].s3 = (tr[rc].s3 * tr[o].lazm * tr[o].lazm * tr[o].lazm) % Mod; 58 tr[lc].s2 = (tr[lc].s2 * tr[o].lazm * tr[o].lazm) % Mod; 59 tr[rc].s2 = (tr[rc].s2 * tr[o].lazm * tr[o].lazm) % Mod; 60 tr[lc].s1 = (tr[lc].s1 * tr[o].lazm) % Mod; 61 tr[rc].s1 = (tr[rc].s1 * tr[o].lazm) % Mod; 62 tr[lc].lazm = (tr[lc].lazm * tr[o].lazm) % Mod; 63 tr[rc].lazm = (tr[rc].lazm * tr[o].lazm) % Mod; 64 tr[o].lazm = 1; 65 } 66 } 67 68 void build(int o, int l, int r) { 69 tr[o].clear(); 70 if(l == r) return; 71 int mid = (l + r) >> 1; 72 build(lc, l, mid); 73 build(rc, mid + 1, r); 74 } 75 76 void add(int o, int l, int r) { 77 if(l != r) pushdown(o, l, r); 78 if(x <= l && r <= y) { 79 tr[o].s3 = (tr[o].s3 + z * tr[o].s2 * 3 + z * z * tr[o].s1 * 3 + z * z * z * (r - l + 1)) % Mod; 80 tr[o].s2 = (tr[o].s2 + z * tr[o].s1 * 2 + z * z * (r - l + 1)) % Mod; 81 tr[o].s1 = (tr[o].s1 + z * (r - l + 1)) % Mod; 82 tr[o].laza = (tr[o].laza + z) % Mod; 83 return; 84 } 85 int mid = (l + r) >> 1; 86 if(x <= mid) add(lc, l, mid); 87 if(y > mid) add(rc, mid + 1, r); 88 pushup(o); 89 } 90 91 void multiply(int o, int l, int r) { 92 if(l != r) pushdown(o, l, r); 93 if(x <= l && r <= y) { 94 tr[o].s3 = (tr[o].s3 * z * z * z) % Mod; 95 tr[o].s2 = (tr[o].s2 * z * z) % Mod; 96 tr[o].s1 = (tr[o].s1 * z) % Mod; 97 tr[o].lazm = (tr[o].lazm * z) % Mod; 98 return; 99 } 100 int mid = (l + r) >> 1; 101 if(x <= mid) multiply(lc, l, mid); 102 if(y > mid) multiply(rc, mid + 1, r); 103 pushup(o); 104 } 105 106 void cover(int o, int l, int r) { 107 if(l != r) pushdown(o, l, r); 108 if(x <= l && r <= y) { 109 tr[o].s3 = z * z * z * (r - l + 1) % Mod; 110 tr[o].s2 = z * z * (r - l + 1) % Mod; 111 tr[o].s1 = z * (r - l + 1) % Mod; 112 tr[o].lazc = z; 113 return; 114 } 115 int mid = (l + r) >> 1; 116 if(x <= mid) cover(lc, l, mid); 117 if(y > mid) cover(rc, mid + 1, r); 118 pushup(o); 119 } 120 121 ll ask(int o, int l, int r) { 122 if(l != r) pushdown(o, l, r); 123 if(x <= l && r <= y) { 124 switch(z) { 125 case 1:return tr[o].s1; 126 case 2:return tr[o].s2; 127 case 3:return tr[o].s3; 128 } 129 } 130 ll res = 0; 131 int mid = (l + r) >> 1; 132 if(x <= mid) res += ask(lc, l, mid); 133 if(y > mid) res += ask(rc, mid + 1, r); 134 return res; 135 } 136 137 int main() { 138 while(scanf("%d %d", &n, &m), n != 0) { 139 build(1, 1, n); 140 while(m --) { 141 scanf("%d %d %d %lld", &op, &x, &y, &z); 142 switch(op) { 143 case 1:add(1, 1, n);break; 144 case 2:multiply(1, 1, n);break; 145 case 3:cover(1, 1, n);break; 146 case 4:printf("%lld\n", ask(1, 1, n));break; 147 } 148 } 149 } 150 return 0; 151 }
原文:http://www.cnblogs.com/ytytzzz/p/6629360.html