Transformation
来源:互联网 发布:在线学编程的网站 编辑:程序博客网 时间:2024/05/15 12:37
Transformation - HDU 4578 - 线段树
题目描述:
Yuanfang is puzzled with the question below:
There are n integers, a 1, a 2, …, a n. The initial values of them are 0. There are four kinds of operations.
Operation 1: Add c to each number between a x and a y inclusive. In other words, do transformation a k<—a k+c, k = x,x+1,…,y.
Operation 2: Multiply c to each number between a x and a y inclusive. In other words, do transformation a k<—a k×c, k = x,x+1,…,y.
Operation 3: Change the numbers between a x and a y to c, inclusive. In other words, do transformation a k<—c, k = x,x+1,…,y.
Operation 4: Get the sum of p power among the numbers between a x and a y inclusive. In other words, get the result of a x p+a x+1 p+…+a y p.
Yuanfang has no idea of how to do it. So he wants to ask you to help him.
Input
There are no more than 10 test cases.
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.
Output
For each operation 4, output a single integer in one line representing the result. The answer may be quite large. You just need to calculate the remainder of the answer when divided by 10007.
Sample Input
5 53 3 5 71 2 4 44 1 5 22 2 5 84 3 5 30 0
Sample Output
3077489
题意:给你n个初始化为0的数,然后给你m个操作,每行操作对应四个整数type u v num
,四种操作类型:
type=1:把区间[u,v]
所有数都+num。
type=2:把区间[u,v]
所有数都*num。
type=3:把区间[u,v]
所有数都赋值为num。
type=4:输出区间[u,v]
所有数的num
次方和(1<=num<=3)。
思路:更新的时候涉及到如果两种或三种标记同时存在的时候如何处理。
在这里我选择优先处理赋值操作,因为一个区间如果一旦经过赋值操作以后,add标记和mult标记自然而然地需要变成0。
然后是加法和乘法的先后问题,在这里我选择在乘法操作中加一点小小的处理,如果在处理当前区间的过程中发现存在加法标记add,那么把add标记变成add*num,然后再执行乘法操作。
这样一来,在pushdown()
过程中就一定是最先处理same,然后是multi,最后是add。
WA了很多发,检查到最后,发现,仅仅是忘了模。心态崩了。
附上AC代码:
//// main.cpp// L//// Created by LucienShui on 2017/6/2.// Copyright © 2017年 LucienShui. All rights reserved.//#include <iostream>#include <algorithm>#include <set>#include <string>#include <vector>#include <queue>#include <map>#include <stack>#include <iomanip>#include <cstdio>#include <cstring>#include <cmath>#include <cctype>#define memset(a,b,n) memset(a,b,n*sizeof(a[0]))#define il inline#define ll long long#define ull unsigned long longusing namespace std;#define ls (u<<1)#define rs (u<<1|1)#define lson u<<1,l,mid#define rson u<<1|1,mid+1,r#define MOD 10007#define maxn 100007int add[maxn<<2],mult[maxn<<2],same[maxn<<2],sum[maxn<<2][4],sz[maxn<<2],sum1,sum2,sum3,tmp2,tmp3;//add加法标记,mult乘法标记,same赋值标记,sum线段树节点,sz每个节点对应的区间长度void fun_add(int u, int num) { add[u] = (add[u]+num)%MOD; sum1 = sum[u][1],sum2 = sum[u][2],sum3 = sum[u][3]; sum[u][1] += (num*sz[u])%MOD;//更新一次方的和 sum[u][1] %= MOD; tmp2 = (num * num)%MOD; sum[u][2] += sum1*num*2%MOD + (tmp2*sz[u])%MOD;//根据完全平方公式更新二次方的和 sum[u][2] %= MOD; tmp3 = (tmp2 * num)%MOD; sum[u][3] += (3*tmp2*sum1)%MOD + (3*sum2*num)%MOD + (tmp3*sz[u])%MOD;//根据完全立方公式和更新三次方的和 sum[u][3] %= MOD;}void fun_mult(int u,int num) { if(mult[u]) mult[u] = (mult[u]*num)%MOD; else mult[u] = num; add[u] = (add[u]*num)%MOD;//如果当前节点存在加法标记,奖其更改为add*num sum1 = sum[u][1],sum2 = sum[u][2],sum3 = sum[u][3]; sum[u][1] = (sum1*num)%MOD; tmp2 = (num*num)%MOD; sum[u][2] = (sum2*tmp2)%MOD; tmp3 = (tmp2*num)%MOD; sum[u][3] = (sum3*tmp3)%MOD;}void fun_same(int u, int num) { same[u] = num; add[u] = mult[u] = 0; sum[u][1] = (num*sz[u])%MOD; tmp2 = (num*num)%MOD; sum[u][2] = (tmp2*sz[u])%MOD; tmp3 = (tmp2*num)%MOD; sum[u][3] = (tmp3*sz[u])%MOD;}void pushup(int u) {//从子树更新父节点 sum[u][1] = (sum[ls][1] + sum[rs][1])%MOD; sum[u][2] = (sum[ls][2] + sum[rs][2])%MOD; sum[u][3] = (sum[ls][3] + sum[rs][3])%MOD;}void pushdown(int u) {//清除三种lazy标记 if(same[u]) { fun_same(ls,same[u]); fun_same(rs,same[u]); same[u]=0; } if(mult[u]) { fun_mult(ls,mult[u]); fun_mult(rs,mult[u]); mult[u]=0; } if(add[u]) { fun_add(ls,add[u]); fun_add(rs,add[u]); add[u]=0; }}void build(int u, int l, int r) {//递归建树 if(l==r) { add[u] = mult[u] = same[u] = 0; sum[u][1] = sum[u][2] = sum[u][3] = 0; sz[u] = 1; return ; } add[u] = mult[u] = same[u] = 0; sum[u][1] = sum[u][2] = sum[u][3] = 0; int mid = (l+r)>>1; build(lson); build(rson); sz[u] = sz[ls] + sz[rs];//记得向上回溯sz数组}void update(int u, int l, int r, int b, int e, int num, int type) { if(b <= l && r <= e) { if(type==1) fun_add(u,num); else if(type==2) fun_mult(u,num); else fun_same(u,num); return ; } pushdown(u); int mid = (l+r)>>1; if(b<=mid) update(lson,b,e,num,type); if(e>mid) update(rson,b,e,num,type); pushup(u);}int query(int u, int l, int r, int b, int e, int pow) { if(b <= l && r<=e) return sum[u][pow]; pushdown(u); int mid = (l+r)>>1; if(e<=mid) return query(lson,b,e,pow)%MOD;//记得模MOD else if(b>mid) return query(rson,b,e,pow)%MOD; return (query(lson,b,e,pow)+query(rson,b,e,pow))%MOD;}int main (){#ifndef ONLINE_JUDGE freopen("in.txt","r",stdin);#endif // ONLINE_JUDGE int n,m; while(scanf("%d%d",&n,&m),n!=0&&m!=0) { int type,b,e,num; build(1,1,n); for(int i=1 ; i<=m ; i++) { scanf("%d%d%d%d",&type,&b,&e,&num); if(type==4) printf("%d\n",query(1,1,n,b,e,num)); else update(1,1,n,b,e,num,type); } } return 0;}
- Transformation
- Rotation transformation
- affine transformation
- lookup transformation
- Computer Transformation
- Reassociation Transformation
- OpenGL Transformation
- Affine Transformation
- Shanks transformation
- Image Transformation
- OpenGL Transformation
- Spark transformation
- UVa1647Computer Transformation
- Number Transformation
- hdu4578 Transformation
- USACO: Transformation
- affine transformation
- hdu4952Number Transformation
- 列对象+创建对象类型+使用对象类型定义表中的列/DML操作
- Android—java实现apk的静默安装、普通安装
- Spring Spring-data-redis 实现的消息队列
- Javaee -----01----javaee的环境搭建和html标签
- Hinton神经网络公开课编程题2--神经概率语言模型(NNLM)
- Transformation
- smarty待续
- 机房收费系统之一(如何学习)
- 三步解决android studio 工程上传不到github
- 把jdbc又翻看了一遍,感觉竟然还收获颇丰
- eclipse中如何创建带文件头的xml文件
- 实现Android 动态加载APK(Fragment or Activity实现)
- 单例模式--饿汉式
- 文章标题