[HDOJ4578]Transformation(线段树,多延迟标记)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578
四种操作:查询、加法、乘法、改数。应该是需要维护三个lazy标记,然后就是套路了。查询是区间内所有的数的p次幂然后再求和,这个p只有三个值(1,2,3),直接维护三棵线段树,分别是1 2 3次幂。
注意延迟标记的时候,如果有改数,那之前的加法和乘法就可以不用做了。在更新乘法的时候,如果有加法存在,那加法的标记应该更新,乘一下乘法的数,因为(a+b)*c = a*c+b*c,父亲是a+b,儿子是a和b。
pushdown的顺序就是:改数、乘法、加法。三种询问好处理,(a+b)^2和(a+b)^3展开就行了。
这是我做过的比较复杂的线段树了。
/*
┓┏┓┏┓┃キリキリ♂ mind!
┛┗┛┗┛┃\○/
┓┏┓┏┓┃ /
┛┗┛┗┛┃ノ)
┓┏┓┏┓┃
┛┗┛┗┛┃
┓┏┓┏┓┃
┛┗┛┗┛┃
┓┏┓┏┓┃
┛┗┛┗┛┃
┓┏┓┏┓┃
┃┃┃┃┃┃
┻┻┻┻┻┻
*/
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
using namespace std;
#define fr first
#define sc second
#define cl clear
#define BUG puts("here!!!")
#define W(a) while(a--)
#define pb(a) push_back(a)
#define Rlf(a) scanf("%lf", &a);
#define Rint(a) scanf("%d", &a)
#define Rll(a) scanf("%I64d", &a)
#define Rs(a) scanf("%s", a)
#define Cin(a) cin >> a
#define FRead() freopen("in", "r", stdin)
#define FWrite() freopen("out", "w", stdout)
#define Rep(i, len) for(int i = 0; i < (len); i++)
#define For(i, a, len) for(int i = (a); i < (len); i++)
#define Cls(a) memset((a), 0, sizeof(a))
#define Clr(a, x) memset((a), (x), sizeof(a))
#define Full(a) memset((a), 0x7f7f, sizeof(a))
#define lrt rt << 1
#define rrt rt << 1 | 1
#define pi 3.14159265359
#define RT return
#define lowbit(x) x & (-x)
#define onenum(x) __builtin_popcount(x)
typedef long long LL;
typedef long double LD;
typedef unsigned long long ULL;
typedef pair<int, int> pii;
typedef pair<string, int> psi;
typedef map<string, int> msi;
typedef vector<int> vi;
typedef vector<LL> vl;
typedef vector<vl> vvl;
typedef vector<bool> vb; inline bool scan_d(int &num) {
char in;bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<''||in>'')) in=getchar();
if(in=='-'){ IsN=true;num=;}
else num=in-'';
while(in=getchar(),in>=''&&in<=''){
num*=,num+=in-'';
}
if(IsN) num=-num;
return true;
} const int mod = ;
const int maxn = ; LL add[maxn<<], put[maxn<<], mul[maxn<<];
LL sum1[maxn<<], sum2[maxn<<], sum3[maxn<<]; void pushUP(int rt) {
sum1[rt] = (sum1[lrt] + sum1[rrt]) % mod;
sum2[rt] = (sum2[lrt] + sum2[rrt]) % mod;
sum3[rt] = (sum3[lrt] + sum3[rrt]) % mod;
} void pushDOWN(int rt, int m) {
if(put[rt]) {
put[lrt] = put[rrt] = put[rt];
add[lrt] = add[rrt] = ;
mul[lrt] = mul[rrt] = ;
sum1[lrt] = (m - (m >> )) % mod * put[rt] % mod;
sum1[rrt] = (m >> ) % mod * put[rt] % mod;
sum2[lrt] = (m - (m >> )) % mod * put[rt] % mod * put[rt] % mod;
sum2[rrt] = (m >> ) % mod * put[rt] % mod * put[rt] % mod;
sum3[lrt] = (m - (m >> ) % mod) * (put[rt] * put[rt]) % mod * put[rt] % mod % mod;
sum3[rrt] = (m >> ) % mod * put[rt] * put[rt] % mod * put[rt] % mod % mod;
put[rt] = ;
}
if(mul[rt] != ) {
mul[lrt] = mul[lrt] * mul[rt] % mod;
mul[rrt] = mul[rrt] * mul[rt] % mod;
if(add[lrt]) add[lrt] = (add[lrt] * mul[rt]) % mod;
if(add[rrt]) add[rrt] = (add[rrt] * mul[rt]) % mod;
sum1[lrt] = (sum1[lrt] * mul[rt]) % mod;
sum1[rrt] = (sum1[rrt] * mul[rt]) % mod;
sum2[lrt] = (sum2[lrt] * mul[rt]) % mod * mul[rt] % mod;
sum2[rrt] = (sum2[rrt] * mul[rt]) % mod * mul[rt] % mod;
sum3[lrt] = (sum3[lrt] * mul[rt]) % mod * mul[rt] % mod * mul[rt] % mod;
sum3[rrt] = (sum3[rrt] * mul[rt]) % mod * mul[rt] % mod * mul[rt] % mod;
mul[rt] = ;
}
if(add[rt]) {
add[lrt] = (add[lrt] + add[rt]) % mod;
add[rrt] = (add[rrt] + add[rt]) % mod;
sum3[lrt] = (sum3[lrt] + ((add[rt] * add[rt] % mod) * add[rt] % mod * (m - (m >> )) % mod) + * add[rt] * ((sum2[lrt] + sum1[lrt] * add[rt]) % mod)) % mod;
sum3[rrt] = (sum3[rrt] + ((add[rt] * add[rt] % mod) * add[rt] % mod * (m >> ) % mod) + * add[rt] * ((sum2[rrt] + sum1[rrt] * add[rt]) % mod)) % mod;
sum2[lrt] = (sum2[lrt] + ((add[rt] * add[rt] % mod) * (m - (m >> )) % mod) + ( * sum1[lrt] * add[rt] % mod)) % mod;
sum2[rrt] = (sum2[rrt] + (((add[rt] * add[rt] % mod) * (m >> )) % mod) + ( * sum1[rrt] * add[rt] % mod)) % mod;
sum1[lrt] = (sum1[lrt] + (m - (m >> )) * add[rt]) % mod;
sum1[rrt] = (sum1[rrt] + (m >> ) * add[rt]) % mod;
add[rt] = ;
}
} void build(int l, int r, int rt) {
add[rt] = put[rt] = ; mul[rt] = ;
sum1[rt] =sum2[rt] = sum3[rt] = ;
if(l == r) return;
int m = (l + r) >> ;
build(l, m, lrt);
build(m+, r, rrt);
} void update(int L, int R, int c, int ch, int l, int r, int rt) {
if(L <= l && r <= R) {
if(ch == ) {
put[rt] = c;
add[rt] = ;
mul[rt] = ;
sum1[rt] = ((r - l + ) * c) % mod;
sum2[rt] = (((r - l + ) * c) % mod * c) % mod;
sum3[rt] = ((((r - l + ) * c) % mod * c) % mod * c) % mod;
}
if(ch == ) {
mul[rt] = (mul[rt] * c) % mod;
if(add[rt]) add[rt] = (add[rt] * c) % mod;
sum1[rt] = (sum1[rt] * c) % mod;
sum2[rt] = ((sum2[rt] * c) % mod * c) % mod;
sum3[rt] = (((sum3[rt] * c) % mod * c) % mod * c) % mod;
}
if(ch == ) {
add[rt] += c;
sum3[rt] = (sum3[rt] + (((c * c) % mod * c) % mod * (r - l + )) % mod + * c * ((sum2[rt] + sum1[rt] * c) % mod)) % mod;
sum2[rt] = (sum2[rt] + (c * c % mod * (r - l + ) % mod) + * sum1[rt] * c) % mod;
sum1[rt] = (sum1[rt] + (r - l + ) * c) % mod;
}
return;
}
pushDOWN(rt, r-l+);
int m = (l + r) >> ;
if(R <= m) update(L, R, c, ch, l, m, lrt);
else if(L > m) update(L, R, c, ch, m+, r, rrt);
else {
update(L, R, c, ch, l, m, lrt);
update(L, R, c, ch, m+, r, rrt);
}
pushUP(rt);
} LL query(int L, int R, int p, int l, int r, int rt) {
if(L <= l && r <= R) {
if(p == ) return sum1[rt] % mod;
if(p == ) return sum2[rt] % mod;
if(p == ) return sum3[rt] % mod;
}
pushDOWN(rt, r-l+);
int m = (l + r) >> ;
if(R <= m) return query(L, R, p, l, m, lrt);
else if(m < L) return query(L, R, p, m+, r, rrt);
else return (query(L, R, p, l, m, lrt) + query(L, R, p, m+, r, rrt)) % mod;
} int n, m;
int a, b, c, ch; int main() {
// FRead();
while(~scan_d(n) && ~scan_d(m) && n + m) {
build(, n, );
W(m) {
scan_d(ch); scan_d(a); scan_d(b); scan_d(c);
if(ch != ) update(a, b, c, ch, , n, );
else cout << query(a, b, c, , n, ) << endl;
}
}
RT ;
}
[HDOJ4578]Transformation(线段树,多延迟标记)的更多相关文章
- FZU 2171(线段树的延迟标记)
题意:容易理解. 分析:时隔很久,再一次写了一道线段树的代码,之前线段树的题也做了不少,包括各种延迟标记,但是在组队分任务之后,我们队的线段树就交给了另外一个队友在搞, 然后我就一直没去碰线段树的题了 ...
- poj 3468 A Simple Problem with Integers 线段树加延迟标记
A Simple Problem with Integers Description You have N integers, A1, A2, ... , AN. You need to deal ...
- 线段树初步&&lazy标记
线段树 一.概述: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a, ...
- Fast Arrangement (线段树,延迟标志)
个人心得:线段树的延迟标志确实是减少了很多时间,思想比较简单,但是实现得时候和建立延迟的时候比较麻烦. 按照我的一些理解,就是更新时找到完全覆盖的区间时,更新延迟标志,不再往下更新,但此时父节点啥的都 ...
- HDU 4578 Transformation --线段树,好题
题意: 给一个序列,初始全为0,然后有4种操作: 1. 给区间[L,R]所有值+c 2.给区间[L,R]所有值乘c 3.设置区间[L,R]所有值为c 4.查询[L,R]的p次方和(1<=p< ...
- 【BZOJ-2892&1171】强袭作战&大sz的游戏 权值线段树+单调队列+标记永久化+DP
2892: 强袭作战 Time Limit: 50 Sec Memory Limit: 512 MBSubmit: 45 Solved: 30[Submit][Status][Discuss] D ...
- BZOJ 1798 (线段树||分块)的标记合并
我原来准备做方差的.. 结果发现不会维护两个标记.. 就是操作变成一个 a*x+b ,每次维护a , b 即可 加的时候a=1 ,b=v 乘的时候a=v ,b=0 #include <cstdi ...
- POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)
题目链接:http://poj.org/problem?id=3237 一棵有边权的树,有3种操作. 树链剖分+线段树lazy标记.lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每 ...
- hdu 1828 Picture(线段树 || 普通hash标记)
http://acm.hdu.edu.cn/showproblem.php?pid=1828 Picture Time Limit: 6000/2000 MS (Java/Others) Mem ...
- poj3468 线段树的懒惰标记
题目链接:poj3468 题意:给定一段数组,有两种操作,一种是给某段区间加c,另一种是查询一段区间的和 思路:暴力的方法是每次都给这段区间的点加c,查询也遍历一遍区间,复杂度是n*n,肯定过不去,另 ...
随机推荐
- IOS 基于APNS消息推送原理与实现(JAVA后台)
Push的原理: Push 的工作机制可以简单的概括为下图 图中,Provider是指某个iPhone软件的Push服务器,这篇文章我将使用.net作为Provider. APNS 是Apple Pu ...
- WPF解析Word为图片
偶遇需要解析Word为单张图,此做 http://git.oschina.net/jiailiuyan/OfficeDecoder using System; using System.Collect ...
- c++ void,内存操作函数
void的含义 void的字面意思是“无类型”, void * 则为“无类型指针”, void * 可以指向任何类型的数据 void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变 ...
- c++ 枚举 在函数中的应用
#include <iostream> using namespace std; enum RespErrNo { SUCCESS = , INVALID_URL = , INVALID_ ...
- vim分屏快捷键使用/增大/减小字体使用
问题描述: vim分屏快捷键使用 问题解决: (1)vim 分屏快捷键 (2)vim高度改变 (3)vim中增加和减少字体大小 使用快捷键Ctr ...
- jquery常用函数与方法汇总
1.delay(duration,[queueName]) 设置一个延时来推迟执行队列中之后的项目. jQuery1.4新增.用于将队列中的函数延时执行.他既可以推迟动画队列的执行,也可以用于自定义队 ...
- 【BZOJ】【2463】【中山市选2009】谁能赢呢?
博弈论 这能算博弈论吗…… orz ZYF so sad……窝智商太低 题解搬运: 当n为偶数时,可以被2*1的骨牌完全覆盖,所以每次都走骨牌的另一端,而另一个人只能走新的骨牌,直到没有为止 当n为奇 ...
- websphere变成英文了怎么变回中文
今天进来发现,websphere在浏览器里面居然是英文的.这是因为我的浏览器少了一个中文语言设置,其实和页面编码无关. 解决办法: IE浏览器右键属性 -- internet选项 -- 常规 -- ...
- [设计模式] 17 中介者模式 Mediator Pattern
在GOF的<设计模式:可复用面向对象软件的基础>一书中对中介者模式是这样说的:用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变 ...
- WinForm 资源文件的使用
1. 创建资源文件: 2.双击资源文件,打开如下图:添加一个字符串: 名称为cnnstr 值为-- 3.添加文本文件和图像 4. 调用代码 MessageBox.Show(Resource1.cnns ...