HDU4578 Transformation(多标记线段树)题解
题意:
操作有:\(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(多标记线段树)题解的更多相关文章
- HDU4578 Transformation (多操作线段树)
传送门 终于过了这道题.. 要注意标记之间的影响,和add操作时更新求和的顺序. same 区间每个数设置为x标记 mult 区间每个数乘x标记 add 区间每个数加x标记 ①:当打same标记时 ...
- CSU 2151 集训难度【多标记线段树】
http://acm.csu.edu.cn/csuoj/problemset/problem?pid=2151 Input 第一行三个数n,m,v0 表示有n名萌新和m次调整,初始时全部萌新的集训难度 ...
- Petrozavodsk Summer Training Camp 2016H(多标记线段树)题解
题意: \(n\)个草,第\(0\)天种下,高度都为\(0\),每个草每天长高\(a_i\).现给出\(q\)询问,每次给出第\(b_i\)天,然后把高于\(d_i\)的全削成\(d_i\),每次问你 ...
- HDU 5029 Relief grain 树链剖分打标记 线段树区间最大值
Relief grain Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid= ...
- POJ - 2777——Count Color(懒标记线段树二进制)
Count Color Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 53639 Accepted: 16153 Des ...
- POJ1389:Area of Simple Polygons——扫描线线段树题解+全套代码注释
http://poj.org/problem?id=1389 题面描述在二维xy平面中有N,1 <= N <= 1,000个矩形.矩形的四边是水平或垂直线段.矩形由左下角和右上角的点定义. ...
- 「洛谷 P3834」「模板」可持久化线段树 题解报告
题目描述 给定n个整数构成的序列,将对于指定的闭区间查询其区间内的第k小值. 输入输出格式 输入格式 第一行包含两个正整数n,m,分别表示序列的长度和查询的个数. 第二行包含n个整数,表示这个序列各项 ...
- HDU 1556 Color the Ball 线段树 题解
本题使用线段树自然能够,由于区间的问题. 这里比較难想的就是: 1 最后更新须要查询全部叶子节点的值,故此须要使用O(nlgn)时间效率更新全部点. 2 截取区间不能有半点差错.否则答案错误. 这两点 ...
- POJ 2528 Mayor's posters 离散化和线段树题解
本题就是要往墙上贴海报,问最后有多少可见的海报. 事实上本题的难点并非线段树,而是离散化. 由于数据非常大,直接按原始数据计算那么就会爆内存和时间的. 故此须要把数据离散化. 比方有海报1 6 7 ...
- poj 3468 A Simple Problem with Integers 线段树 题解《挑战程序设计竞赛》
地址 http://poj.org/problem?id=3468 线段树模板 要背下此模板 线段树 #include <iostream> #include <vector> ...
随机推荐
- ClickHouse入门:表引擎-HDFS
前言插件及服务器版本服务器:ubuntu 16.04Hadoop:2.6ClickHouse:20.9.3.45 文章目录 简介 引擎配置 HDFS表引擎的两种使用形式 引用 简介 ClickHous ...
- css-前端实现左中右三栏布局的常用方法:绝对定位,圣杯,双飞翼,flex,table-cell,网格布局等
1.前言 作为一个前端开发人员,工作学习中经常会遇到快速构建网页布局的情况,这篇我整理了一下我知道的一些方法.我也是第一次总结,包括圣杯布局,双飞翼布局,table-cell布局都是第一次听说,可能会 ...
- 前端知识(一)06 element-ui-谷粒学院
目录 一.element-ui 二.element-ui实例 1.引入脚本库 2.引入css 3.引入js 4.渲染讲师列表 5.浏览器中运行 一.element-ui element-ui 是饿了么 ...
- python多线程和GIL全局解释器锁
1.线程 线程被称为轻量级进程,是最小执行单元,系统调度的单位.线程切换需要的资源一般,效率一般. 2.多线程 在单个程序中同时运行多个线程完成不同的工作,称为多线程 3.并 ...
- Python+Selenium+Unittest实现PO模式web自动化框架(7)
1.TestDatas目录的功能 TestDatas目录下存放的是测试数据,比如:登录功能的测试用例数据. # --^_^-- coding:utf-8 --^_^-- # @Remark:登录测试数 ...
- VMware中安装Ubuntu后,安装VMwareTools提示“Not enough free space to extract VMwareTools-10.3.10-13959562.tar.gz”的解决办法
将加载后的Vmware Tools中的*.tar.gz文件复制到桌面后提取,否则会报错:
- CODING 再携手腾讯云 Serverless,让开发者跑步上云
近年来,腾讯云持续在云原生领域打磨和完善产品矩阵,致力于为开发者上云提供更好的产品和服务.继前段时间 CODING CI 助力腾讯云 Serverless 全新应用控制台.持续保障 Serverles ...
- 中央事件总线 事件驱动架构(EDA) 解析事件总线的4种实现方式
事件驱动架构(EDA)https://mp.weixin.qq.com/s/nA8XFD2Rx_7qA_LxltGGHw https://mp.weixin.qq.com/s/cD3auglgKzOb ...
- C # 9.0的record
官方消息: c # 9.0已经过时了!早在五月份,我就在博客中介绍了 c # 9.0计划,下面是该文章的更新版本,以便与我们最终发布的计划相匹配. 对于每一个新的 c # 版本,我们都在努力提高常见编 ...
- #define typedef 区别
1) #define是预处理指令,在编译预处理时进行简单的替换,不作正确性检查,不关含义是否正确照样带入,只有在编译已被展开的源程序时才会发现可能的错误并报错.例如: #define PI 3.141 ...