HDU 4578 - Transformation - [加强版线段树]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578
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.
题意:
给出一个序列,有下列操作:
- 对区间[x,y]全部加上c
- 对区间[x,y]全部乘上c
- 将区间[x,y]全部改成c
- 查询区间[x,y]的p次方和
题解:
加强版的线段树,需要三个lazy标记,一个add表示加法标记,一个mul表示乘法标记,一个alt表示修改标记,
同时由于p=1,2,3,所以可以有三个val值:sum1表示一次方和,sum2表示平方和,sum3表示立方和,
然后我们要确定三个标记的优先级:alt第一,mul第二,add第三,pushdown的时候要按照这样的顺序pushdown,
同时下压高优先级的标记,会影响到低优先级的标记,这个需要注意,
另外,在接收到父节点传过来的add标记时,更新自身时(update_add成员函数),要注意计算sum3,sum2,sum1的先后顺序,一定是sum3,sum2,sum1,
这三个sum计算的方法如下:
$\begin{array}{l} \left( {a + x} \right)^2 = a^2 + 2ax + x^2 \\ \left( {a_1 + x} \right)^2 + \left( {a_2 + x} \right)^2 + \cdots + \left( {a_n + x} \right)^2 = \left( {a_1 ^2 + \cdots + a_n ^2 } \right) + 2x\left( {a_1 + \cdots + a_n } \right) + nx^2 \\ \left( {a + x} \right)^3 = a^3 + 3a^2 x + 3ax^2 + x^3 \\ \left( {a_1 + x} \right)^3 + \left( {a_2 + x} \right)^3 + \cdots + \left( {a_n + x} \right)^3 = \left( {a_1 ^3 + \cdots + a_n ^3 } \right) + 3x\left( {a_1 ^2 + \cdots + a_n ^2 } \right) + 3x^2 \left( {a_1 + \cdots + a_n } \right) + nx^3 \\ \end{array}$
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=+;
const int MOD=; int n,m; /********************************* Segment Tree - st *********************************/
struct Node
{
int l,r;
int sum1,sum2,sum3;
int add,mul,alt;
void Update_Alt(int x)
{
x%=MOD;
sum1 = (r-l+) * x % MOD;
sum2 = (r-l+) * x % MOD * x % MOD;
sum3 = (r-l+) * x % MOD * x % MOD * x % MOD;
alt=x;
add=;
mul=;
}
void Update_Mul(int x)
{
x%=MOD;
sum1 = sum1 % MOD * x % MOD;
sum2 = sum2 % MOD * x % MOD * x % MOD;
sum3 = sum3 % MOD * x % MOD * x % MOD * x % MOD;
mul = mul % MOD * x % MOD;
add = add % MOD * x % MOD;
}
void Update_Add(int x)
{
x%=MOD;
sum3 = ( sum3%MOD + *x%MOD*sum2%MOD + *x%MOD*x%MOD*sum1%MOD + (r-l+)*x%MOD*x%MOD*x%MOD ) % MOD;
sum2 = ( sum2%MOD + *x%MOD*sum1%MOD + (r-l+)%MOD*x%MOD*x%MOD ) % MOD;
sum1 = ( sum1%MOD + (r-l+)%MOD*x%MOD ) % MOD;
add=(add%MOD+x)%MOD;
}
}node[*maxn];
void Pushdown(int root)
{
int ls=root*, rs=root*+;
if(node[root].alt!=)
{
node[ls].Update_Alt(node[root].alt);
node[rs].Update_Alt(node[root].alt);
node[root].alt=;
}
if(node[root].mul!=)
{
node[ls].Update_Mul(node[root].mul);
node[rs].Update_Mul(node[root].mul);
node[root].mul=;
}
if(node[root].add!=)
{
node[ls].Update_Add(node[root].add);
node[rs].Update_Add(node[root].add);
node[root].add=;
}
}
void Pushup(int root)
{
int ls=root*, rs=root*+;
node[root].sum1=(node[ls].sum1+node[rs].sum1)%MOD;
node[root].sum2=(node[ls].sum2+node[rs].sum2)%MOD;
node[root].sum3=(node[ls].sum3+node[rs].sum3)%MOD;
}
void Build(int root,int l,int r) //对区间[l,r]建树
{
if(l>r) return;
node[root].l=l; node[root].r=r;
node[root].sum1=;
node[root].sum2=;
node[root].sum3=;
node[root].alt=;
node[root].add=;
node[root].mul=; if(l<r)
{
int mid=l+(r-l)/;
Build(root*,l,mid);
Build(root*+,mid+,r);
Pushup(root);
}
}
void Alt(int root,int st,int ed,ll val) //区间[st,ed]全部改成val
{
if(st>node[root].r || ed<node[root].l) return;
if(st<=node[root].l && node[root].r<=ed) node[root].Update_Alt(val);
else
{
Pushdown(root);
Alt(root*,st,ed,val);
Alt(root*+,st,ed,val);
Pushup(root);
}
}
void Mul(int root,int st,int ed,ll val) //区间[st,ed]全部加上val
{
if(st>node[root].r || ed<node[root].l) return;
if(st<=node[root].l && node[root].r<=ed) node[root].Update_Mul(val);
else
{
Pushdown(root);
Mul(root*,st,ed,val);
Mul(root*+,st,ed,val);
Pushup(root);
}
}
void Add(int root,int st,int ed,ll val) //区间[st,ed]全部加上val
{
if(st>node[root].r || ed<node[root].l) return;
if(st<=node[root].l && node[root].r<=ed) node[root].Update_Add(val);
else
{
Pushdown(root);
Add(root*,st,ed,val);
Add(root*+,st,ed,val);
Pushup(root);
}
}
int Query(int root,int st,int ed,int p) //查询区间[st,ed]的p次方和
{
if(st>node[root].r || ed<node[root].l) return ;
if(st<=node[root].l && node[root].r<=ed)
{
if(p==) return node[root].sum1;
if(p==) return node[root].sum2;
if(p==) return node[root].sum3;
}
else
{
Pushdown(root);
int ls=Query(root*,st,ed,p)%MOD;
int rs=Query(root*+,st,ed,p)%MOD;
Pushup(root);
return (ls+rs)%MOD;
}
}
/********************************* Segment Tree - st *********************************/ int main()
{
while(scanf("%d%d",&n,&m) && n*m!=)
{
Build(,,n);
for(int i=;i<=m;i++)
{
int op; scanf("%d",&op);
if(op==)
{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
Add(,x,y,k);
}
if(op==)
{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
Mul(,x,y,k);
}
if(op==)
{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
Alt(,x,y,k);
}
if(op==)
{
int l,r,p;
scanf("%d%d%d",&l,&r,&p);
printf("%d\n",Query(,l,r,p));
}
}
}
}
HDU 4578 - Transformation - [加强版线段树]的更多相关文章
- HDU 4578 Transformation (线段树)
Transformation Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others)T ...
- HDU 4578——Transformation——————【线段树区间操作、确定操作顺序】
Transformation Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others)T ...
- HDU - 4578 Transformation(线段树区间修改)
https://cn.vjudge.net/problem/HDU-4578 题意 4种操作,区间加,区间乘,区间变为一个数,求区间的和.平方和以及立方和. 分析 明显线段树,不过很麻烦..看kuan ...
- HDU 4578 Transformation (线段树区间多种更新)
http://acm.hdu.edu.cn/showproblem.php?pid=4578 题目大意:对于一个给定序列,序列内所有数的初始值为0,有4种操作.1:区间(x, y)内的所有数字全部加上 ...
- hdu 4578 Transformation(线段树)
线段树上的多操作... 题目大意: 树上 的初始值为0,然后有下列三种操作和求和. 1 x y c 在X-Y的之间全部加上C. 2 x y c 在X-Y的之间全部乘上C. 3 x y c ...
- Hdu 4578 Transformation (线段树 分类分析)
Transformation Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others)T ...
- hdu 5700区间交(线段树)
区间交 Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...
- Snacks HDU 5692 dfs序列+线段树
Snacks HDU 5692 dfs序列+线段树 题意 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充, ...
- HDU 4578 Transformation --线段树,好题
题意: 给一个序列,初始全为0,然后有4种操作: 1. 给区间[L,R]所有值+c 2.给区间[L,R]所有值乘c 3.设置区间[L,R]所有值为c 4.查询[L,R]的p次方和(1<=p< ...
随机推荐
- C 语言与动态库相关基础知识
1.导入文件<>和“”的区别 #include <xxx.h>导入的是标准目录下的.h文件,所谓的标准目录指的是:/use/local/include(一般是第三方头文件)以及 ...
- CMD 切换管理员权限
方法一:鼠标右键 这个方法比较比较普通,点开开始找到cmd,右击鼠标“以管理员身份运行(A)”这样调用就是管理员的权限: 方法二:快捷模式 在点开win+R后,选择“以管理员身份运行”,然后确定:可以 ...
- eclipse中设置文件的编码格式为utf-8
1.可以在 eclipse 中配置 workspace 项下 text file encoding 属性的值来决定此工作区间下所有的 eclipse 项目的文档的编码属性. Window-->P ...
- Tomcat catalina-deamon.out 日志切割 每天生成一个文件
Tomcat 使用 jsvc 以守护进程的方式启动(daemon.sh ).这样tomcat自身将会生成另外一个日志文件(catalina-daemon.out),而不是之前的catalina.out ...
- switch和continue的关系
突然想到 我们用 switch都是用 break return等关键字来配合,有没有一种情况下是用continue呢?而且如果真的出现了continue,结果是什么样的呢?
- fork(), waitpid()
NAME fork - create a child process SYNOPSIS #include <unistd.h> pid_t fork(void); RETURN VALUE ...
- DRBD架构详解(原创)
DRBD概述Distributed Replicated Block Device(DRBD)是一种基于软件的,无共享,复制的存储解决方案,在服务器之间的对块设备(硬盘,分区,逻辑卷等)进行镜像.DR ...
- mybatis 之 parameterType="java.util.List"
<!-- 添加 --> <insert id="saveBatchMemberRoleConnRepModel" parameterType="java ...
- vue再次入手(数据传递②)
接上篇~ 5.最后一种,互通:无所谓父组件或者是子组件,而是随时随地都能调用到数据的一种方法.便是利用vuex来管理数据,官网描述: Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它 ...
- 来数一数XML解析成为Dataset数据
最近在看一些接口,所以目标就是写接口啦,但是我想说的是公司的业务还不曾了解,所以自己先来做一个小小的demo练习吧,主要知道需要和xml有关系的,但是之前从来没有接触过解析xml文件的,在玩撒谎能够搜 ...