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> ...
随机推荐
- 给dtcms增加模板自动生成功能
作为dtcms的使用者你是不是像我一样,也在不停的修改模板之后要点击生成模板浪费了很多开发模板的时间? 那就跟我一起给dtcms增加一个开发者模式,当模板修改完成之后,直接刷新页面就能看到效果,而不再 ...
- Servlet中的一些注意事项
servlet中的一些注意事项 1 什么是servlet? 1)Servlet是Sun公司制定的一套技术标准,包含与Web应用相关的一系列接口,是Web应用实现方式的宏观解决方案.而具体的Servle ...
- fastjson的deserializer的主要优化算法 漏洞
JSON最佳实践 | kimmking's blog http://kimmking.github.io/2017/06/06/json-best-practice/ Fastjson内幕 Java综 ...
- loj10012 Best Cow Fences
题目描述 原题来自:USACO 2003 Mar. Green 给定一个长度为 N 的非负整数序列 A ,求一个平均数最大的,长度不小于 L 的子段. 输入格式 第一行用空格分隔的两个整数 N 和 L ...
- k8s之集群管理
导读 经过前面k8s系列的文章,这一系列已经基本完成,现在就用几篇文章说一下日常的集群维护. 目录 更新资源对象的Label Namespace:集群环境共享与隔离 部署集群监控 部署Web UI管理 ...
- 【wp】HWS计划2021硬件安全冬令营线上选拔赛
逆向手在夹缝中艰难求生系列. 这篇真的存粹是做题笔记了,对内核驱动啥的不太懂,pwn也不会,能做出来的题都是硬逆出来的( childre最后死活没整出来,后来看大佬的wp才知道对子进程有修改(.)呜呜 ...
- Docker是如何实现隔离的
Docker是如何实现隔离的 2.进程的隔离 4.文件的隔离 5.资源的限制 7.与传统虚拟机技术的区别 原文地址: 微信公众号:<鲁智深菜园子>:Docker是如何实现隔离的 # 1.运 ...
- Java——I/O,字节流与字符流,BufferedOutputStream,InputStream等(附相关练习代码)
I/O: I/O是什么? 在程序中,所有的数据都是以流的形式进行传输或者保存. 程序需要数据的时候,就要使用输入流读取数据. 程序需要保存数据的时候,就要使用输出流来完成. 程序的输入以及输出都是以流 ...
- java架构《并发线程高级篇三》
本章主要介绍和讲解concurrent.util里面的常用的工具类. 一.CountDownLatch使用:(用于阻塞主线程) 应用场景 :通知线程休眠和运行的工具类,是wait和notify的升级版 ...
- vmware打开虚拟级断电情况下,无法找到虚拟机文件
1.此时会在建立的虚拟机目录下,有一些 %虚拟机名字%.vmx.lck 或者别的 %虚拟机名字%.***.lck 删除这些文件夹 2.虚拟文件 是一个后缀名为vmx的文件,发现断电后 变成了v ...