题意:

操作有:\(1\).区间都加\(a\);\(2\).区间都乘\(a\);\(3\).区间都重置成\(a\);\(4\).询问区间幂次和\(\sum_{i=l}^rnum[i]^p(p\in\{1,2,3\})\)

思路:

设一个数为\(m*sum+a\),加就变成了\(m*sum+a+a_2\),乘就变成了\(m*m_2*sum+a*m_2\)。令\(add\)为加标记,\(mul\)为乘标记。

\(mul\)向下\(pushdown\)要给\(add\)也乘上,并且\(mul\)要比\(add\)先\(pushdown\)。\(add\)向下\(pushdown\)直接加就行。

重置的\(pushdown\)优先级要最高,在更新重置时就要把\(mul = 1,add= 0\)。

高次幂的和可以转化成低次幂的乱搞操作。

代码:

#include<map>
#include<set>
#include<queue>
#include<stack>
#include<ctime>
#include<cmath>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 100000 + 5;
const int INF = 0x3f3f3f3f;
const ull seed = 131;
const ll MOD = 10007;
using namespace std;
ll n, m;
ll sum[4][maxn << 2], add[maxn << 2], mul[maxn << 2], change[maxn << 2];
ll ppow(ll a, ll b){
ll ret = 1;
while(b){
if(b & 1) ret = ret * a % MOD;
b >>= 1;
a = a * a % MOD;
}
return ret;
}
void pushup(int rt){
for(int i = 1; i <= 3; i++)
sum[i][rt] = (sum[i][rt << 1] + sum[i][rt << 1 | 1]) % MOD;
} void pushdown(int rt, int l, int r){
int m = (l + r) >> 1;
if(change[rt]){
for(int i = 1; i <= 3; i++) sum[i][rt << 1] = ppow(change[rt], i) * (m - l + 1) % MOD;
for(int i = 1; i <= 3; i++) sum[i][rt << 1 | 1] = ppow(change[rt], i) * (r - m) % MOD;
change[rt << 1] = change[rt << 1 | 1] = change[rt];
mul[rt << 1] = mul[rt << 1 | 1] = 1;
add[rt << 1] = add[rt << 1 | 1] = 0;
}
if(mul[rt] != 1){
sum[3][rt << 1] = sum[3][rt << 1] * ppow(mul[rt], 3) % MOD;
sum[3][rt << 1 | 1] = sum[3][rt << 1 | 1] * ppow(mul[rt], 3) % MOD; sum[2][rt << 1] = sum[2][rt << 1] * ppow(mul[rt], 2) % MOD;
sum[2][rt << 1 | 1] = sum[2][rt << 1 | 1] * ppow(mul[rt], 2) % MOD; sum[1][rt << 1] = sum[1][rt << 1] * mul[rt] % MOD;
sum[1][rt << 1 | 1] = sum[1][rt << 1 | 1] * mul[rt] % MOD; mul[rt << 1] = mul[rt << 1] * mul[rt] % MOD;
mul[rt << 1 | 1] = mul[rt << 1 | 1] * mul[rt] % MOD;
add[rt << 1] = add[rt << 1] * mul[rt] % MOD;
add[rt << 1 | 1] = add[rt << 1 | 1] * mul[rt] % MOD; }
if(add[rt]){
sum[3][rt << 1] = (sum[3][rt << 1] + 3LL * add[rt] * sum[2][rt << 1] + 3LL * ppow(add[rt], 2) * sum[1][rt << 1] + (m - l + 1) * ppow(add[rt], 3)) % MOD;
sum[3][rt << 1 | 1] = (sum[3][rt << 1 | 1] + 3LL * add[rt] * sum[2][rt << 1 | 1] + 3LL * ppow(add[rt], 2) * sum[1][rt << 1 | 1] + (r - m) * ppow(add[rt], 3)) % MOD; sum[2][rt << 1] = (sum[2][rt << 1] + 2LL * add[rt] * sum[1][rt << 1] + ppow(add[rt], 2) * (m - l + 1)) % MOD;
sum[2][rt << 1 | 1] = (sum[2][rt << 1 | 1] + 2LL * add[rt] * sum[1][rt << 1 | 1] + ppow(add[rt], 2) * (r - m)) % MOD; sum[1][rt << 1] = (sum[1][rt << 1] + add[rt] * (m - l + 1)) % MOD;
sum[1][rt << 1 | 1] = (sum[1][rt << 1 | 1] + add[rt] * (r - m)) % MOD; add[rt << 1] = (add[rt << 1] + add[rt]) % MOD;
add[rt << 1 | 1] = (add[rt << 1 | 1] + add[rt]) % MOD;
} mul[rt] = 1, add[rt] = 0, change[rt] = 0; }
void build(int l, int r, int rt){
add[rt] = 0;
mul[rt] = 1;
change[rt] = 0;
if(l == r){
sum[1][rt] = sum[2][rt] = sum[3][rt] = 0;
return;
}
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
pushup(rt);
}
void update(int L, int R, int l, int r, ll v, int op, int rt){
if(L <= l && R >= r){
if(op == 1){ //add
sum[3][rt] = (sum[3][rt] + 3LL * v * sum[2][rt] + 3LL * v * v * sum[1][rt] + (r - l + 1LL) * v * v * v) % MOD;
sum[2][rt] = (sum[2][rt] + 2LL * v * sum[1][rt] + (r - l + 1LL) * v * v) % MOD;
sum[1][rt] = (sum[1][rt] + v * (r - l + 1)) % MOD;
add[rt] += v;
}
else if(op == 2){ //mul
sum[1][rt] = sum[1][rt] * v % MOD;
sum[2][rt] = sum[2][rt] * v * v % MOD;
sum[3][rt] = sum[3][rt] * v * v * v % MOD;
mul[rt] = mul[rt] * v % MOD;
add[rt] = add[rt] * v % MOD;
}
else{ //set
sum[1][rt] = v * (r - l + 1) % MOD;
sum[2][rt] = v * v * (r - l + 1) % MOD;
sum[3][rt] = v * v * v * (r - l + 1) % MOD;
mul[rt] = 1, add[rt] = 0, change[rt] = v;
}
return;
}
pushdown(rt, l, r);
int m = (l + r) >> 1;
if(L <= m)
update(L, R, l, m, v, op, rt << 1);
if(R > m)
update(L, R, m + 1, r, v, op, rt << 1 | 1);
pushup(rt);
}
ll query(int L, int R, int l, int r, int v, int rt){
if(L <= l && R >= r){
return sum[v][rt];
}
pushdown(rt, l, r);
ll ret = 0;
int m = (l + r) >> 1;
if(L <= m)
ret += query(L, R, l, m, v, rt << 1);
if(R > m)
ret += query(L, R, m + 1, r, v, rt << 1 | 1);
return ret % MOD;
}
int main(){
while(~scanf("%lld%lld", &n, &m) && n + m){
build(1, n, 1);
while(m--){
int op, x, y, c;
scanf("%d%d%d%d", &op, &x, &y, &c);
if(op <= 3) update(x, y, 1, n, c, op, 1);
else printf("%lld\n", query(x, y, 1, n, c, 1));
}
}
return 0;
}

HDU4578 Transformation(多标记线段树)题解的更多相关文章

  1. HDU4578 Transformation (多操作线段树)

    传送门 终于过了这道题.. 要注意标记之间的影响,和add操作时更新求和的顺序. same 区间每个数设置为x标记 mult  区间每个数乘x标记 add  区间每个数加x标记 ①:当打same标记时 ...

  2. CSU 2151 集训难度【多标记线段树】

    http://acm.csu.edu.cn/csuoj/problemset/problem?pid=2151 Input 第一行三个数n,m,v0 表示有n名萌新和m次调整,初始时全部萌新的集训难度 ...

  3. Petrozavodsk Summer Training Camp 2016H(多标记线段树)题解

    题意: \(n\)个草,第\(0\)天种下,高度都为\(0\),每个草每天长高\(a_i\).现给出\(q\)询问,每次给出第\(b_i\)天,然后把高于\(d_i\)的全削成\(d_i\),每次问你 ...

  4. HDU 5029 Relief grain 树链剖分打标记 线段树区间最大值

    Relief grain Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid= ...

  5. POJ - 2777——Count Color(懒标记线段树二进制)

    Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 53639   Accepted: 16153 Des ...

  6. POJ1389:Area of Simple Polygons——扫描线线段树题解+全套代码注释

    http://poj.org/problem?id=1389 题面描述在二维xy平面中有N,1 <= N <= 1,000个矩形.矩形的四边是水平或垂直线段.矩形由左下角和右上角的点定义. ...

  7. 「洛谷 P3834」「模板」可持久化线段树 题解报告

    题目描述 给定n个整数构成的序列,将对于指定的闭区间查询其区间内的第k小值. 输入输出格式 输入格式 第一行包含两个正整数n,m,分别表示序列的长度和查询的个数. 第二行包含n个整数,表示这个序列各项 ...

  8. HDU 1556 Color the Ball 线段树 题解

    本题使用线段树自然能够,由于区间的问题. 这里比較难想的就是: 1 最后更新须要查询全部叶子节点的值,故此须要使用O(nlgn)时间效率更新全部点. 2 截取区间不能有半点差错.否则答案错误. 这两点 ...

  9. POJ 2528 Mayor&#39;s posters 离散化和线段树题解

    本题就是要往墙上贴海报,问最后有多少可见的海报. 事实上本题的难点并非线段树,而是离散化. 由于数据非常大,直接按原始数据计算那么就会爆内存和时间的. 故此须要把数据离散化. 比方有海报1 6   7 ...

  10. poj 3468 A Simple Problem with Integers 线段树 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=3468 线段树模板 要背下此模板 线段树 #include <iostream> #include <vector> ...

随机推荐

  1. Linux Centos7之由Python2升级到Python3教程

    1.先查看当前系统Python版本,默认都是Python2.7,命令如下: [root@localhost gau]# python -V Python 2.7.5 2.安装Python3,安装方法很 ...

  2. USB2514集线器调试总结

    一般的MCU不会留有太多的USB口,但在实际项目中又会遇到需要很多个USB口的情况,这时就会用到USB集线器来扩展USB口了.USB2514这个芯片是我在工作中用的比较多的,但是问题很多,从来没有调稳 ...

  3. CACTI优化-流量接口统计total输入和输出流量数据

    看图,没有优化前(没有显示流入和流出的总流量是多少): 优化后(有显示流入和流出总流量统计): 如何实现呢?本节就是处理的过程小结.第一步:登陆cacti管理平台进入控制台->模板->图形 ...

  4. Let’s Encrypt/Certbot移除/remove/revoke不需要的域名证书

    1.首先确认你的证书不再需要,如果有必要,请执行下面的命令进行备份 cp /etc/letsencrypt/ /etc/letsencrypt.backup -r 2.撤销证书然后删除证书 [root ...

  5. (01)-Python3之--字符串操作

    1.字符串切片取值 字符串的取值通过索引来读取,从0开始. 取区间值如下:字符串变量名[起始索引:结束索引].包含起始,但不包含结束.例如: str_my = "hello,python!我 ...

  6. 学习es6构造函数的第一天

    什么是面向对象 编程思维分为,面向过程和面向对象 面向过程就像一个人,一间屋子,一个床 一个人走进了屋子,上了床 二面向对象 人,屋子,床 可以是屋子里进了一个人,上了床 或者,屋子里的床上有一个人 ...

  7. Fiddler扩展——自定义列数据&Tunnel to 443解决办法

    在平时日常工作中,使用Fiddler的占比还是蛮大的.使用过程,也会遇到一些小问题,问题虽小,但抓不到包,分析不了问题与数据,那也是件麻烦的事情. 以前也分享过一些小技巧,可以找以前的博文查看,具体地 ...

  8. linux yum rpm 和 apt-get dpkg 安装、卸载软件

      一般来说著名的linux系统基本上分两大类:   1.RedHat系列:Redhat.Centos.Fedora等   2.Debian系列:Debian.Ubuntu等   RedHat 系列  ...

  9. jenkins 简介和简单操作

    持续集成:Continuous Intergration (CI) 持续交付:Continuous Delivery(CD) 持续部署:Continuous Deployment(CD) jenkin ...

  10. EIGRP和OSPF__邻居发现

    散知识点 1.当配置通配符时,它们的取值总是块尺寸减去1:/28的块尺寸为16,因此当我们添加网络声明时,使用了此子网号和一个在需配置的八位位组中添加值为15的通配符. 邻居发现 1.在EIGRP路由 ...