hdu 4578(区间更新)
2015-08-25 14:15
225 查看
题意:有长度为n的序列,初始都为0,然后有四种操作,1 a b c表示区间[a,b]所有数字加c,2 a b c表示区间[a,b]所有数字都乘c,3 a b c表示区间[a,b]所有数字都设置为c,4 a b p表示输区间[a,b]所有数字的p次方的和,结果模10007。
题解:因为p的取值是1到3,可以开三个线段树分别维护区间内p次方的和,根据(a+c)^2 = a^2+2ac+c^2,(a+c)^3 = a^3+3a^2c+3ac^2+c^3维护平方和和立方和。标记传递因为操作3会覆盖操作1和2,所以操作3要先传递,然后传递操作2,因为操作1的标记addv[k]可以变为addv[k]*c。
题解:因为p的取值是1到3,可以开三个线段树分别维护区间内p次方的和,根据(a+c)^2 = a^2+2ac+c^2,(a+c)^3 = a^3+3a^2c+3ac^2+c^3维护平方和和立方和。标记传递因为操作3会覆盖操作1和2,所以操作3要先传递,然后传递操作2,因为操作1的标记addv[k]可以变为addv[k]*c。
#include <cstdio> #include <cstring> #include <algorithm> #define ll long long using namespace std; const int N = 100005; const int MOD = 10007; int n, m; ll tree[N << 2][3], addv[N << 2], mulv[N << 2], setv[N << 2]; void pushup(int k) { for (int i = 0; i < 3; i++) tree[k][i] = (tree[k * 2][i] + tree[k * 2 + 1][i]) % MOD; } void pushdown(int k, int left, int right) { int mid = (left + right) / 2; int lenl = mid - left + 1, lenr = right - mid; if (setv[k]) { tree[k * 2][0] = (setv[k] * lenl) % MOD; tree[k * 2 + 1][0] = (setv[k] * lenr) % MOD; ll temp = (setv[k] * setv[k]) % MOD; tree[k * 2][1] = (temp * lenl) % MOD; tree[k * 2 + 1][1] = (temp * lenr) % MOD; temp = (temp * setv[k]) % MOD; tree[k * 2][2] = (temp * lenl) % MOD; tree[k * 2 + 1][2] = (temp * lenr) % MOD; setv[k * 2] = setv[k * 2 + 1] = setv[k]; addv[k * 2] = addv[k * 2 + 1] = 0; mulv[k * 2] = mulv[k * 2 + 1] = 0; setv[k] = 0; } if (mulv[k]) { for (int i = 0; i < 2; i++) if (mulv[k * 2 + i]) mulv[k * 2 + i] = (mulv[k * 2 + i] * mulv[k]) % MOD; else mulv[k * 2 + i] = mulv[k]; addv[k * 2] = (addv[k * 2] * mulv[k]) % MOD; addv[k * 2 + 1] = (addv[k * 2 + 1] * mulv[k]) % MOD; tree[k * 2][0] = (tree[k * 2][0] * mulv[k]) % MOD; tree[k * 2 + 1][0] = (tree[k * 2 + 1][0] * mulv[k]) % MOD; ll temp = (mulv[k] * mulv[k]) % MOD; tree[k * 2][1] = (tree[k * 2][1] * temp) % MOD; tree[k * 2 + 1][1] = (tree[k * 2 + 1][1] * temp) % MOD; temp = (temp * mulv[k]) % MOD; tree[k * 2][2] = (tree[k * 2][2] * temp) % MOD; tree[k * 2 + 1][2] = (tree[k * 2 + 1][2] * temp) % MOD; mulv[k] = 0; } if (addv[k]) { addv[k * 2] = (addv[k * 2] + addv[k]) % MOD; addv[k * 2 + 1] = (addv[k * 2 + 1] + addv[k]) % MOD; ll suml = tree[k * 2][0], sumr = tree[k * 2 + 1][0]; ll suml2 = tree[k * 2][1], sumr2 = tree[k * 2 + 1][1]; tree[k * 2][0] = (tree[k * 2][0] + (addv[k] * lenl) % MOD) % MOD; tree[k * 2 + 1][0] = (tree[k * 2 + 1][0] + (addv[k] * lenr) % MOD) % MOD; ll temp = (addv[k] * addv[k]) % MOD; tree[k * 2][1] = (tree[k * 2][1] + (addv[k] * 2 * suml) % MOD + (temp * lenl) % MOD) % MOD; tree[k * 2 + 1][1] = (tree[k * 2 + 1][1] + (addv[k] * 2 * sumr) % MOD + (temp * lenr) % MOD) % MOD; ll temp2 = (temp * addv[k]) % MOD; tree[k * 2][2] = (tree[k * 2][2] + (temp * 3 * suml) % MOD + (addv[k] * 3 * suml2) % MOD + (temp2 * lenl) % MOD) % MOD; tree[k * 2 + 1][2] = (tree[k * 2 + 1][2] + (temp * 3 * sumr) % MOD + (addv[k] * 3 * sumr2) % MOD + (temp2 * lenr) % MOD) % MOD; addv[k] = 0; } } void modify(int k, int left, int right, int l, int r, ll x, int op) { if (l <= left && right <= r) { int len = right - left + 1; if (op == 1) { addv[k] = (addv[k] + x) % MOD; ll sum1 = tree[k][0], sum2 = tree[k][1]; tree[k][0] = (tree[k][0] + x * len) % MOD; ll temp = (x * x) % MOD; tree[k][1] = (tree[k][1] + (2 * x * sum1) % MOD + (temp * len) % MOD) % MOD; ll temp2 = (temp * x) % MOD; tree[k][2] = (tree[k][2] + (3 * temp * sum1) % MOD + (3 * sum2 * x) % MOD + (temp2 * len) % MOD) % MOD; } else if (op == 2) { if (mulv[k]) mulv[k] = (mulv[k] * x) % MOD; else mulv[k] = x; addv[k] = (addv[k] * x) % MOD; tree[k][0] = (tree[k][0] * x) % MOD; ll temp = (x * x) % MOD; tree[k][1] = (tree[k][1] * temp) % MOD; temp = (x * temp) % MOD; tree[k][2] = (tree[k][2] * temp) % MOD; } else if (op == 3) { setv[k] = x; addv[k] = mulv[k] = 0; tree[k][0] = (x * len) % MOD; ll temp = (x * x) % MOD; tree[k][1] = (temp * len) % MOD; temp = (temp * x) % MOD; tree[k][2] = (temp * len) % MOD; } return; } pushdown(k, left, right); int mid = (left + right) / 2; if (l <= mid) modify(k * 2, left, mid, l, r, x, op); if (r > mid) modify(k * 2 + 1, mid + 1, right, l, r, x, op); pushup(k); return; } ll query(int k, int left, int right, int l, int r, int p) { if (l <= left && right <= r) return tree[k][p]; pushdown(k, left, right); int mid = (left + right) / 2; ll temp = 0; if (l <= mid) temp += query(k * 2, left, mid, l, r, p); if (r > mid) temp += query(k * 2 + 1, mid + 1, right, l, r, p); pushup(k); return temp % MOD; } int main() { while (scanf("%d%d", &n, &m) == 2 && m + n) { memset(tree, 0, sizeof(tree)); memset(addv, 0, sizeof(addv)); memset(mulv, 0, sizeof(mulv)); memset(setv, 0, sizeof(setv)); int op, l, r; ll x; while (m--) { scanf("%d%d%d%lld", &op, &l, &r, &x); if (op != 4) modify(1, 1, n, l, r, x, op); else printf("%lld\n", query(1, 1, n, l, r, x - 1)); } } return 0; }
相关文章推荐
- WMS介绍
- 反转字符串I am a student
- Java中的日历类Calendar的常用方法(所有方法都在客户端测试过)
- 如何更新Android SDK和Build Tool
- UIViewController生命周期需要注意的
- 【POJ2492】【加权并查集模板题】
- 简道云如何实现零售行业抄单管理 | 数据管理
- BA-接触器常见故障解决方法
- 关于android studio几种常见的错误解决
- js toArray的更好实现方法
- 8.2.1.12 Outer Join Simplification 外联接简化
- ubuntu使用ap-hotspot建立WIFI热点
- 黑马程序员--OC学习篇之Foundation框架中的NSString对象和NSMutableString对象
- 06-图7. How Long Does It Take (25)
- RAC+DG搭建过程
- 阿里笔试--软开C/C++
- Java批量插入数据
- 《Java溯本求源》-Java基本数据类型
- 模板特化
- decorators.xml