题目链接: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(线段树,多延迟标记)的更多相关文章

  1. FZU 2171(线段树的延迟标记)

    题意:容易理解. 分析:时隔很久,再一次写了一道线段树的代码,之前线段树的题也做了不少,包括各种延迟标记,但是在组队分任务之后,我们队的线段树就交给了另外一个队友在搞, 然后我就一直没去碰线段树的题了 ...

  2. poj 3468 A Simple Problem with Integers 线段树加延迟标记

    A Simple Problem with Integers   Description You have N integers, A1, A2, ... , AN. You need to deal ...

  3. 线段树初步&&lazy标记

    线段树 一.概述: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a, ...

  4. Fast Arrangement (线段树,延迟标志)

    个人心得:线段树的延迟标志确实是减少了很多时间,思想比较简单,但是实现得时候和建立延迟的时候比较麻烦. 按照我的一些理解,就是更新时找到完全覆盖的区间时,更新延迟标志,不再往下更新,但此时父节点啥的都 ...

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

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

  6. 【BZOJ-2892&1171】强袭作战&大sz的游戏 权值线段树+单调队列+标记永久化+DP

    2892: 强袭作战 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 45  Solved: 30[Submit][Status][Discuss] D ...

  7. BZOJ 1798 (线段树||分块)的标记合并

    我原来准备做方差的.. 结果发现不会维护两个标记.. 就是操作变成一个 a*x+b ,每次维护a , b 即可 加的时候a=1 ,b=v 乘的时候a=v ,b=0 #include <cstdi ...

  8. POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)

    题目链接:http://poj.org/problem?id=3237 一棵有边权的树,有3种操作. 树链剖分+线段树lazy标记.lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每 ...

  9. hdu 1828 Picture(线段树 || 普通hash标记)

    http://acm.hdu.edu.cn/showproblem.php?pid=1828 Picture Time Limit: 6000/2000 MS (Java/Others)    Mem ...

  10. poj3468 线段树的懒惰标记

    题目链接:poj3468 题意:给定一段数组,有两种操作,一种是给某段区间加c,另一种是查询一段区间的和 思路:暴力的方法是每次都给这段区间的点加c,查询也遍历一遍区间,复杂度是n*n,肯定过不去,另 ...

随机推荐

  1. Linux C C语言库的创建和调用

    C语言库的创建和调用 简介: 假如,你有一个庞大的工程,代码量达到数百兆甚至是数G,你经常会遇到好多重复或常用的地方.每次使用到这些地方时如果都重新写一份基本相同的代码,这当然可以,不过这样会大大地降 ...

  2. Java反射在JVM的实现

    1. 什么是Java反射,有什么用?反射使程序代码能够接入装载到JVM中的类的内部信息,允许在编写与执行时,而不是源代码中选定的类协作的代码,是以开发效率换运行效率的一种手段.这使反射成为构建灵活应用 ...

  3. 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 ...

  4. python学习小结1:for循环控制语句

    用一个列表来确定for循环的范围 >>> x = [0,1,2,3,4] >>> for i in x: print i, 0 1 2 3 4  循环一个字符串 & ...

  5. .NET开源项目介绍及资源推荐:数据持久层

    在.NET平台下,关于数据持久层框架非常多,本文主要对如下几种做简要的介绍并推荐一些学习的资源: 1.NHibernate 2.NBear 3.Castle ActiveRecord 4.iBATIS ...

  6. Wireshark - ICMP 报文分析

    1. 测试机器,源 IP 地址为 10.21.28.110,目的 IP 地址为 10.6.0.24. 2. 使用 "ip.addr == 10.6.0.24 and icmp" 过 ...

  7. 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文件.  ...

  8. 2006: [NOI2010]超级钢琴 - BZOJ

    Description小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为 ...

  9. STL中的单向队列queue

    转载自:http://blog.csdn.net/morewindows/article/details/6950917 stl中的queue指单向队列,使用时,包含头文件<queue>. ...

  10. [设计模式] 7 桥接模式 bridge

    #include<iostream> using namespace std; class AbstractionImp { public: virtual ~AbstractionImp ...