[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,肯定过不去,另 ...
随机推荐
- Linux C C语言库的创建和调用
C语言库的创建和调用 简介: 假如,你有一个庞大的工程,代码量达到数百兆甚至是数G,你经常会遇到好多重复或常用的地方.每次使用到这些地方时如果都重新写一份基本相同的代码,这当然可以,不过这样会大大地降 ...
- Java反射在JVM的实现
1. 什么是Java反射,有什么用?反射使程序代码能够接入装载到JVM中的类的内部信息,允许在编写与执行时,而不是源代码中选定的类协作的代码,是以开发效率换运行效率的一种手段.这使反射成为构建灵活应用 ...
- Another 20 Docs and Guides for Front-End Developers
http://www.sitepoint.com/another-20-docs-guides-front-end-developers/?utm_medium=email&utm_campa ...
- python学习小结1:for循环控制语句
用一个列表来确定for循环的范围 >>> x = [0,1,2,3,4] >>> for i in x: print i, 0 1 2 3 4 循环一个字符串 & ...
- .NET开源项目介绍及资源推荐:数据持久层
在.NET平台下,关于数据持久层框架非常多,本文主要对如下几种做简要的介绍并推荐一些学习的资源: 1.NHibernate 2.NBear 3.Castle ActiveRecord 4.iBATIS ...
- Wireshark - ICMP 报文分析
1. 测试机器,源 IP 地址为 10.21.28.110,目的 IP 地址为 10.6.0.24. 2. 使用 "ip.addr == 10.6.0.24 and icmp" 过 ...
- unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor
eclipse启动项目时,提示超时: 解决方案: 修改 workspace\.metadata\.plugins\org.eclipse.wst.server.core\servers.xml文件. ...
- 2006: [NOI2010]超级钢琴 - BZOJ
Description小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为 ...
- STL中的单向队列queue
转载自:http://blog.csdn.net/morewindows/article/details/6950917 stl中的queue指单向队列,使用时,包含头文件<queue>. ...
- [设计模式] 7 桥接模式 bridge
#include<iostream> using namespace std; class AbstractionImp { public: virtual ~AbstractionImp ...