题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578

Problem Description
Yuanfang is puzzled with the question below: 
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. 
 
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 5
3 3 5 7
1 2 4 4
4 1 5 2
2 2 5 8
4 3 5 3
0 0
 
Sample Output
307
7489

题意:

给出一个序列,有下列操作:

  1. 对区间[x,y]全部加上c
  2. 对区间[x,y]全部乘上c
  3. 将区间[x,y]全部改成c
  4. 查询区间[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 - [加强版线段树]的更多相关文章

  1. HDU 4578 Transformation (线段树)

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others)T ...

  2. HDU 4578——Transformation——————【线段树区间操作、确定操作顺序】

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others)T ...

  3. HDU - 4578 Transformation(线段树区间修改)

    https://cn.vjudge.net/problem/HDU-4578 题意 4种操作,区间加,区间乘,区间变为一个数,求区间的和.平方和以及立方和. 分析 明显线段树,不过很麻烦..看kuan ...

  4. HDU 4578 Transformation (线段树区间多种更新)

    http://acm.hdu.edu.cn/showproblem.php?pid=4578 题目大意:对于一个给定序列,序列内所有数的初始值为0,有4种操作.1:区间(x, y)内的所有数字全部加上 ...

  5. hdu 4578 Transformation(线段树)

    线段树上的多操作... 题目大意: 树上 的初始值为0,然后有下列三种操作和求和. 1  x y c  在X-Y的之间全部加上C. 2  x y c  在X-Y的之间全部乘上C. 3  x y c   ...

  6. Hdu 4578 Transformation (线段树 分类分析)

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others)T ...

  7. hdu 5700区间交(线段树)

    区间交 Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...

  8. Snacks HDU 5692 dfs序列+线段树

    Snacks HDU 5692 dfs序列+线段树 题意 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充, ...

  9. HDU 4578 Transformation --线段树,好题

    题意: 给一个序列,初始全为0,然后有4种操作: 1. 给区间[L,R]所有值+c 2.给区间[L,R]所有值乘c 3.设置区间[L,R]所有值为c 4.查询[L,R]的p次方和(1<=p< ...

随机推荐

  1. NetBpm 测试篇(3)

    http://www.netbpm.org/movie/holiday/holiday.html

  2. Git Step by Step – (5) Git分支(branch)

    在前面两盘文章中介绍了Git的基本原理,都是理论知识.这篇文章我们再次回到实践中,看看Git分支(branch)的使用. 在代码版本控制工具中,都会有branch的概念.刚开始建立版本仓库的时候,我们 ...

  3. RFC文件

    RFC(Request For Comments)-意即“请求评议”,包含了关于Internet的几乎所有重要的文字资料.如果你想成为网络方面的专家,那么RFC无疑是最重要也是最经常需要用到的资料之一 ...

  4. 利用DB实现简单去重处理

    业务需要针对某文件进行判重操作,用Perl实现如下 #!/usr/bin/perl my %h; s/\s+$// and $h{$_}++ while <>; print "$ ...

  5. HTML 注释

    "<!-- xxx -->" 用于在 HTML 中插入注释,注释是用来给开发人员看的,浏览器不会显示注释内容 <!DOCTYPE HTML> <htm ...

  6. 国内CDN加速现状

    什么是CDN CDN的全称是Content Delivery Network,即内容分发网络.是位于网络层与应用层之间的网络应用,其目的是通过在现有的Internet中增加一层新的网络架构,将网站的内 ...

  7. pyinstaller 将.py生成.exe ----报错 “IndexError: tuple index out of range”

    pyinstaller将py打包为exe文件,用pysintaller居然报错 File "c:\anaconda3\lib\site-packages\PyInstaller\depend ...

  8. Linux怎样创建FTP服务器--修改用户默认目录

    在创建FTP服务器之有先命令: ps -ef |grep vsftpd 查一下系统有没有安装vsftpd这个服务器,如果出现如下图所示的界面说明没有安装.     然后再执行:yum install ...

  9. 【摘】50个jQuery代码段帮助你成为一个更好的JavaScript开发者

    今 天的帖子会给你们展示50个jQuery代码片段,这些代码能够给你的JavaScript项目提供帮助.其中的一些代码段是从jQuery1.4.2才 开始支持的做法,另一些则是真正有用的函数或方法,他 ...

  10. codeforces水题100道 第五题 Codeforces Round #304 (Div. 2) A. Soldier and Bananas (math)

    题目链接:http://www.codeforces.com/problemset/problem/546/A题意:一个人现在有n元,它买第i根香蕉需要i*k元,问他要买w根香蕉的话,需要问他的朋友借 ...