hdoj 4578 Transformation 【线段树 区间加、乘、修改、幂次求和】
来源:互联网 发布:端口23连接失败解决 编辑:程序博客网 时间:2024/06/07 03:43
Transformation
Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others)Total Submission(s): 3869 Accepted Submission(s): 956
There are n integers, a1, a2, …, an. The initial values of them are 0. There are four kinds of operations.
Operation 1: Add c to each number between ax and ay inclusive. In other words, do transformation ak<---ak+c, k = x,x+1,…,y.
Operation 2: Multiply c to each number between ax and ay inclusive. In other words, do transformation ak<---ak×c, k = x,x+1,…,y.
Operation 3: Change the numbers between ax and ay to c, inclusive. In other words, do transformation ak<---c, k = x,x+1,…,y.
Operation 4: Get the sum of p power among the numbers between ax and ay inclusive. In other words, get the result of axp+ax+1p+…+ay p.
Yuanfang has no idea of how to do it. So he wants to ask you to help him.
For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000.
Each the following m lines contains an operation. Operation 1 to 3 is in this format: "1 x y c" or "2 x y c" or "3 x y c". Operation 4 is in this format: "4 x y p". (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3)
The input ends with 0 0.
5 53 3 5 71 2 4 44 1 5 22 2 5 84 3 5 30 0
3077489
不停取余,不停取余。。。眼都花了 o(╯□╰)o
题意:给你N个数和Q次操作。
1 x y c 表示区间[x, y]所有数全加c
2 x y c 表示区间[x, y]所有数全乘c
3 x y c 表示区间[x, y]所有数修改为c
4 x y c 求区间[x, y]所有数c次方之和 结果对10007取余。
思路:lazy1 lazy2 lazy3 对应三个操作的标记。sum1 sum2 sum3为区间所有数1、2、3次方之和。len为区间长度。
这里面lazy1 和 lazy2的标记不太好弄,可以简化下。
对一个数a,先加lazy1再乘lazy2,结果为(a + lazy1) * lazy2 = a * lazy2 + lazy1 * lazy2
反过来结果为a * lazy2 + lazy1,我们只需把末尾等效就好了。对lazy1,每当出现lazy2时,乘上就可以了。
单点加c的时候,把三次方公式化简一下就得到
sum3 += 3*c*sum2 + 3*c*c*sum1 + c*c*c*len。sum2类似。
单点乘c的时候,注意lazy1的等效,单点修改c时,lazy1 lazy2取消。后两个公式很简单。
标记下传时,考虑顺序。假设lazy3是最后一个标记,那么我们直接操作它就好了。但是如果它不是最后一个,我们还是要修改它,再对lazy1或者lazy2操作。这样每次先操作lazy3。
lazy3标记下传最简单,直接去掉lazy1和lazy2,修改lazy3就可以了。至于lazy1和lazy2有:
[son].lazy1 = [father].lazy1 + [father].lazy2 * [son].lazy1。[son].lazy2 *= [father].lazy1
记lazy1 lazy2是father向son传的标记,s1、s2、s3为儿子1次、2次、3次方之和。
这样对结果的更新 (a+lazy1)*lazy2 —— a*l2 + l1,已经操作了lazy1 * lazy2
1次方sum1—— a*l2 + l1 = s1 * l2 + len * l1;
2次方sum2——(a*l2 + l1) ^ 2 = s2*l2*l2 + 2*s1*l2*l1 + len*l1*l1;
3次方sum3——(a*l2 + l1) ^ 3 = s3*l2*l2*l2 + 3*s2*l2*l2*l1 + 3*s1*l2*l1*l1 + len*l1*l1*l1;
AC代码:
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#include <queue>#include <stack>#include <map>#include <set>#include <vector>#include <string>#define INF 0x3f3f3f3f#define eps 1e-8#define MAXN (100000+10)#define MAXM (500000)#define Ri(a) scanf("%d", &a)#define Rl(a) scanf("%lld", &a)#define Rf(a) scanf("%lf", &a)#define Rs(a) scanf("%s", a)#define Pi(a) printf("%d\n", (a))#define Pf(a) printf("%.2lf\n", (a))#define Pl(a) printf("%lld\n", (a))#define Ps(a) printf("%s\n", (a))#define W(a) while(a--)#define CLR(a, b) memset(a, (b), sizeof(a))#define MOD 10007#define LL long long#define lson o<<1, l, mid#define rson o<<1|1, mid+1, r#define ll o<<1#define rr o<<1|1#define PI acos(-1.0)using namespace std;struct Tree{ int l, r, len; int sum1, sum2, sum3; int lazy1, lazy2, lazy3;};Tree tree[MAXN<<2];void PushUp(int o){ tree[o].sum1 = (tree[ll].sum1 + tree[rr].sum1) % MOD; tree[o].sum2 = (tree[ll].sum2 + tree[rr].sum2) % MOD; tree[o].sum3 = (tree[ll].sum3 + tree[rr].sum3) % MOD;}void Node(int o, int op, int c){ if(op == 1) { tree[o].lazy1 = (tree[o].lazy1 + c) % MOD; int s1 = tree[o].sum1; int s2 = tree[o].sum2; tree[o].sum1 = (tree[o].sum1 + tree[o].len*c%MOD)%MOD; tree[o].sum2 = (tree[o].sum2 + (2*s1%MOD*c%MOD + c*c%MOD*tree[o].len%MOD)%MOD)%MOD; tree[o].sum3 = (tree[o].sum3 + (3*c%MOD*s2%MOD + 3*c%MOD*c%MOD*s1%MOD + c*c%MOD*c%MOD*tree[o].len%MOD)%MOD)%MOD; } else if(op == 2) { tree[o].lazy1 = tree[o].lazy1 * c % MOD; tree[o].lazy2 = tree[o].lazy2 * c % MOD; tree[o].sum1 = tree[o].sum1 * c % MOD; tree[o].sum2 = tree[o].sum2 * c % MOD * c % MOD; tree[o].sum3 = tree[o].sum3 * c % MOD * c % MOD * c % MOD; } else if(op == 3) { tree[o].lazy1 = 0; tree[o].lazy2 = 1; tree[o].lazy3 = c; tree[o].sum1 = c * tree[o].len % MOD; tree[o].sum2 = tree[o].sum1 * c % MOD; tree[o].sum3 = tree[o].sum2 * c % MOD; }}void Count(int o, int l1, int l2){ int s1 = tree[o].sum1; int s2 = tree[o].sum2; int s3 = tree[o].sum3; tree[o].sum1 = (s1*l2%MOD + tree[o].len*l1%MOD)%MOD; tree[o].sum2 = (s2*l2%MOD*l2%MOD + 2*s1%MOD*l2%MOD*l1%MOD + tree[o].len*l1%MOD*l1%MOD)%MOD; tree[o].sum3 = (s3*l2%MOD*l2%MOD*l2%MOD + 3*s2%MOD*l2%MOD*l2%MOD*l1%MOD + 3*s1%MOD*l2%MOD*l1%MOD*l1%MOD + tree[o].len*l1%MOD*l1%MOD*l1%MOD)%MOD;}void PushDown(int o){ if(tree[o].lazy3 != -1) { Node(ll, 3, tree[o].lazy3); Node(rr, 3, tree[o].lazy3); tree[o].lazy3 = -1; } if(tree[o].lazy1 || tree[o].lazy2 != 1) { tree[ll].lazy1 = (tree[o].lazy1 + tree[ll].lazy1 * tree[o].lazy2 % MOD) % MOD; tree[ll].lazy2 = tree[ll].lazy2 * tree[o].lazy2 % MOD; tree[rr].lazy1 = (tree[o].lazy1 + tree[rr].lazy1 * tree[o].lazy2 % MOD) % MOD; tree[rr].lazy2 = tree[rr].lazy2 * tree[o].lazy2 % MOD; Count(ll, tree[o].lazy1, tree[o].lazy2); Count(rr, tree[o].lazy1, tree[o].lazy2); tree[o].lazy1 = 0; tree[o].lazy2 = 1; }}void Build(int o, int l, int r){ tree[o].l = l; tree[o].r = r; tree[o].len = r-l+1; tree[o].lazy1 = 0; tree[o].lazy2 = 1; tree[o].lazy3 = -1; tree[o].sum1 = tree[o].sum2 = tree[o].sum3 = 0; if(l == r) return ; int mid = (tree[o].l + tree[o].r) >> 1; Build(lson); Build(rson);}void Update(int o, int L, int R, int kind, int c){ if(tree[o].l >= L && tree[o].r <= R) { Node(o, kind, c); return ; } PushDown(o); int mid = (tree[o].l + tree[o].r) >> 1; if(R <= mid) Update(ll, L, R, kind, c); else if(L > mid) Update(rr, L, R, kind, c); else { Update(ll, L, mid, kind, c); Update(rr, mid+1, R, kind, c); } PushUp(o);}int Query(int o, int L, int R, int p){ if(tree[o].l >= L && tree[o].r <= R) { if(p == 1) return tree[o].sum1; else if(p == 2) return tree[o].sum2; else return tree[o].sum3; } PushDown(o); int mid = (tree[o].l + tree[o].r) >> 1; if(R <= mid) return Query(ll, L, R, p); else if(L > mid) return Query(rr, L, R, p); else return (Query(ll, L, mid, p) + Query(rr, mid+1, R, p)) % MOD;}int main(){ int N, Q; while(scanf("%d%d", &N, &Q), N||Q) { Build(1, 1, N); W(Q) { int op, x, y, z; Ri(op); Ri(x); Ri(y); Ri(z); if(op == 4) Pi(Query(1, x, y, z)%MOD); else Update(1, x, y, op, z); } } return 0;}
- hdoj 4578 Transformation 【线段树 区间加、乘、修改、幂次求和】
- 【线段树】区间求和+区间修改(区间加)
- HDU - 4578 Transformation(线段树 区间修改)
- BZOJ 5039([Jsoi2014]序列维护-线段树区间加,区间乘,区间求和)
- 【模板】线段树 区间加+乘,区间求和 (模板题:洛谷P3373)
- HDU ACM 4578 Transformation->线段树-区间修改
- 【线段树】 HDOJ 4578 Transformation
- Hdu 4578 Transformation(区间加值,区间乘值,区间赋值,查询区间的p次方)
- 线段树(区间修改,区间求和)
- codevs1080 线段树(区间修改+区间求和
- hdu 4578 Transformation(区间线段树)
- hdu 4578 Transformation [线段树 区间更新]
- HDOJ 4614 —— 线段树区间更新&区间求和
- POJ3468 区间加,区间求和 线段树模板
- 【线段树】区间求和+单点修改
- hdoj1698Just a Hook【线段树区间修改+区间求和】
- 【模板】线段树_区间最值、区间求和、修改
- 线段树 区间求和模板 (区间修改)
- iOS开发 UI 设计模式
- Web Service 的工作原理
- ROS naviagtion analysis: costmap_2d--Costmap2DROS
- 28. Implement strStr()
- java基础a之多线程
- hdoj 4578 Transformation 【线段树 区间加、乘、修改、幂次求和】
- Symmetric Tree 是不是对称树
- hash单词翻译(BKDR)
- 每天学一点linux(8)--查看文件内容
- 文章收录机制探讨
- SNAP建立索引的时候出现问题
- 抽象数据类型的表示和实现
- 写给那时自己
- 关于标准C语言的预定义宏