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了...又改了1h
改错:
其实最难的地方在于三个标记的优先顺序
首先有覆盖标记,就下传并把儿子的加法标记和乘法标记改为0和1
其次看乘法标记,乘法标记需要更新儿子的加法标记
最后看加法标记
二逼错误:
1.打上覆盖标记后,乘法标记更新为1...乘法标记更新为1不是0!
2.我的ask函数的返回值没有取膜...我可能是脑残吧
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 = 1; 42 tr[o].lazc = 0; 43 } 44 if(tr[o].lazm != 1) { 45 tr[lc].s3 = (tr[lc].s3 * tr[o].lazm * tr[o].lazm * tr[o].lazm) % Mod; 46 tr[rc].s3 = (tr[rc].s3 * tr[o].lazm * tr[o].lazm * tr[o].lazm) % Mod; 47 tr[lc].s2 = (tr[lc].s2 * tr[o].lazm * tr[o].lazm) % Mod; 48 tr[rc].s2 = (tr[rc].s2 * tr[o].lazm * tr[o].lazm) % Mod; 49 tr[lc].s1 = (tr[lc].s1 * tr[o].lazm) % Mod; 50 tr[rc].s1 = (tr[rc].s1 * tr[o].lazm) % Mod; 51 tr[lc].laza = (tr[lc].laza * tr[o].lazm) % Mod; 52 tr[rc].laza = (tr[rc].laza * tr[o].lazm) % Mod; 53 tr[lc].lazm = (tr[lc].lazm * tr[o].lazm) % Mod; 54 tr[rc].lazm = (tr[rc].lazm * tr[o].lazm) % Mod; 55 tr[o].lazm = 1; 56 } 57 if(tr[o].laza) { 58 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; 59 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; 60 tr[lc].s2 = (tr[lc].s2 + tr[o].laza * tr[lc].s1 * 2 + tr[o].laza * tr[o].laza * (mid - l + 1)) % Mod; 61 tr[rc].s2 = (tr[rc].s2 + tr[o].laza * tr[rc].s1 * 2 + tr[o].laza * tr[o].laza * (r - mid)) % Mod; 62 tr[lc].s1 = (tr[lc].s1 + tr[o].laza * (mid - l + 1)) % Mod; 63 tr[rc].s1 = (tr[rc].s1 + tr[o].laza * (r - mid)) % Mod; 64 tr[lc].laza = (tr[lc].laza + tr[o].laza) % Mod; 65 tr[rc].laza = (tr[rc].laza + tr[o].laza) % Mod; 66 tr[o].laza = 0; 67 } 68 } 69 70 void build(int o, int l, int r) { 71 tr[o].clear(); 72 if(l == r) return; 73 int mid = (l + r) >> 1; 74 build(lc, l, mid); 75 build(rc, mid + 1, r); 76 } 77 78 void add(int o, int l, int r) { 79 if(l != r) pushdown(o, l, r); 80 if(x <= l && r <= y) { 81 tr[o].s3 = (tr[o].s3 + z * tr[o].s2 * 3 + z * z * tr[o].s1 * 3 + z * z * z * (r - l + 1)) % Mod; 82 tr[o].s2 = (tr[o].s2 + z * tr[o].s1 * 2 + z * z * (r - l + 1)) % Mod; 83 tr[o].s1 = (tr[o].s1 + z * (r - l + 1)) % Mod; 84 tr[o].laza = (tr[o].laza + z) % Mod; 85 return; 86 } 87 int mid = (l + r) >> 1; 88 if(x <= mid) add(lc, l, mid); 89 if(y > mid) add(rc, mid + 1, r); 90 pushup(o); 91 } 92 93 void multiply(int o, int l, int r) { 94 if(l != r) pushdown(o, l, r); 95 if(x <= l && r <= y) { 96 tr[o].s3 = (tr[o].s3 * z * z * z) % Mod; 97 tr[o].s2 = (tr[o].s2 * z * z) % Mod; 98 tr[o].s1 = (tr[o].s1 * z) % Mod; 99 tr[o].lazm = (tr[o].lazm * z) % Mod; 100 return; 101 } 102 int mid = (l + r) >> 1; 103 if(x <= mid) multiply(lc, l, mid); 104 if(y > mid) multiply(rc, mid + 1, r); 105 pushup(o); 106 } 107 108 void cover(int o, int l, int r) { 109 if(l != r) pushdown(o, l, r); 110 if(x <= l && r <= y) { 111 tr[o].s3 = z * z * z * (r - l + 1) % Mod; 112 tr[o].s2 = z * z * (r - l + 1) % Mod; 113 tr[o].s1 = z * (r - l + 1) % Mod; 114 tr[o].lazc = z; 115 return; 116 } 117 int mid = (l + r) >> 1; 118 if(x <= mid) cover(lc, l, mid); 119 if(y > mid) cover(rc, mid + 1, r); 120 pushup(o); 121 } 122 123 ll ask(int o, int l, int r) { 124 if(l != r) pushdown(o, l, r); 125 if(x <= l && r <= y) { 126 switch(z) { 127 case 1:return tr[o].s1; 128 case 2:return tr[o].s2; 129 case 3:return tr[o].s3; 130 } 131 } 132 ll res = 0; 133 int mid = (l + r) >> 1; 134 if(x <= mid) res += ask(lc, l, mid); 135 if(y > mid) res += ask(rc, mid + 1, r); 136 return res % Mod; 137 } 138 139 int main() { 140 while(scanf("%d %d", &n, &m), n != 0) { 141 build(1, 1, n); 142 while(m --) { 143 scanf("%d %d %d %lld", &op, &x, &y, &z); 144 switch(op) { 145 case 1:add(1, 1, n);break; 146 case 2:multiply(1, 1, n);break; 147 case 3:cover(1, 1, n);break; 148 case 4:printf("%lld ", ask(1, 1, n));break; 149 } 150 } 151 } 152 return 0; 153 }