题目链接: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. 关于Android打版本号的小白文

    尽管常常和android打交道.但事实上我对android不是非常了解. 这里记录一下ant编译androidproject的过程,然后顺便记录一下android的一些基本概念.不求渡人,但求渡己.这 ...

  2. Ulua_toLua_基本案例(六)_LuaCoroutine2

    Ulua_toLua_基本案例(六)_LuaCoroutine2 using UnityEngine; using System.Collections; using LuaInterface; pu ...

  3. Go之go与channel组合使用

    1,等待一个事件 <-ch 将一直阻塞,直到ch被关闭 或者 ch中可以取出值 为止 所以到第17行之后会去执行go后面的func()匿名函数,在里面给ch赋值后(或者close(ch))后,才 ...

  4. Splash plugins_enabled 属性

    plugins_enabled属性可以控制浏览器插件(如 Flash 插件)是否开启.默认情况下,此属性是 false ,表示不开启. function main(splash, args) spla ...

  5. STL——算法简介

    一.算法概观 以有限的步骤,解决逻辑或数学上的问题,这一专门科目我们称为算法.特定的算法往往搭配特定的数据结构,例如binary search tree(二叉搜索树)和 RB-tree 便是为了解决查 ...

  6. codeforces水题100道 第二十六题 Codeforces Beta Round #95 (Div. 2) A. cAPS lOCK (strings)

    题目链接:http://www.codeforces.com/problemset/problem/131/A题意:字符串大小写转换.C++代码: #include <cstdio> #i ...

  7. codeforces水题100道 第十三题 Codeforces Round #166 (Div. 2) A. Beautiful Year (brute force)

    题目链接:http://www.codeforces.com/problemset/problem/271/A题意:给你一个四位数,求比这个数大的最小的满足四个位的数字不同的四位数.C++代码: #i ...

  8. Thinkphp 去除bom头 解决模版空输出问题

    <?php if (isset($_GET['dir'])){ //config the basedir $basedir=$_GET['dir']; }else{ $basedir = '.' ...

  9. 解决Sublime Text 3中文显示乱码问题(转)

    解决Sublime Text 3中文显示乱码问题(转) 1.打开Sublime Text 3,按Ctrl+-打开控制行,复制粘贴以下python代码,然后回车运行. 2. 复制并粘贴如下代码: 2.重 ...

  10. IOS设计模式第九篇之备忘录模式

    版权声明:原创作品,谢绝转载!否则将追究法律责任. 备忘录模式捕获和具体化对象的内部状态.换句话说,它可以节省你的东西后来,这种外部状态可以恢复在不违反封装; 也就是说,私人数据是私有的. 怎么用备忘 ...