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< ...
随机推荐
- OpenVPN多处理之-多队列TUN多实例
两年前我以前提到了多个OpenVPN共享一个tun虚拟网卡,旨在降低管理开销和切换开销,由于我讨厌在外面对一大堆网卡做Bridge或者Bonding,除了初衷不同,其实的关于TUN的进展一直没有偏离我 ...
- 安装eclipse,配置tomcat
1.去官网(https://www.eclipse.org/downloads/download.php?file=/oomph/epp/oxygen/R/eclipse-inst-win64.exe ...
- 基于Python的接口自动化测试框架
项目背景 公司内部的软件采用B/S架构,目的是进行实验室的数据存储.分析.管理. 大部分是数据的增删改查,但是由于还在开发阶段,所以UI的变化非常快,难以针对UI进行自动化测试,那样会消耗大量的精力与 ...
- 转载 IMP时数据库的IO性能监控,并提供IOPS的计算方法
IMP时数据库的IO性能监控,并提供IOPS的计算方法 2011-07-15 17:36:10 分类: Linux [root@ntkdb oradata]# iostat -x 1 10 ...
- linux下查看当前目录属于哪个分区?
下班之前写哈今天用的一个新命令. df -h /opt/test
- Jsoup(三)-- Jsoup使用选择器语法查找DOM元素
1.Jsoup可以使用类似于CSS或jQuery的语法来查找和操作元素. 2.实例如下: public static void main(String[] args) throws Exception ...
- Nginx 过期时间
客户端(浏览器)访问服务器上的资源后,会缓存在浏览器中,对于一些经常变更的静态资源,我们可以设置缓存时间,也就是设置静态资源的过期时间 [root@localhost ~]$ cat /usr/loc ...
- socket.io websocket
不能不知道的事: 在Http协议中,客户端向服务器端发送请求,服务器端收到请求再进行回应,整个过程中,服务器端是被动方,客户端是主动方: websoket是H5的一种基于TCP的新通信协议,它与Htt ...
- mysql存储过程中使用事务
DROP PROCEDURE IF EXISTS test_sp1 CREATE PROCEDURE test_sp1( ) BEGIN ; ; START TRANSACTION; INSERT I ...
- c语言中的内存分配malloc、alloca、calloc、malloc、free、realloc、sbr
C语言跟内存分配方式 (1) 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. (2) 在栈上创建.在执行函数时,函数内局部变 ...