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> ...
随机推荐
- 一种获取context中keys和values的高效方法 | golang
我们知道,在 golang 中的 context 是一个非常重要的包,保存了代码活动的上下文.我们经常使用 WithValue() 这个方法,来往 context 中 传递一些 key value 数 ...
- 数据库性能调优之始: analyze统计信息
摘要:本文简单介绍一下什么是统计信息.统计信息记录了什么.为什么要收集统计信息.怎么收集统计信息以及什么时候收集统计信息. 1 WHY:为什么需要统计信息 1.1 query执行流程 下图描述了Gau ...
- java-数据类型复习
java中共有8种基本的数据类型,分别为 字节型byte(8字节,32位),短整型short(16字节),整型int(32字节),长整型long(64字节), 字符型char(16字节),浮点型flo ...
- CSRF Cross-site request forgery 跨站请求伪造
跨站请求伪造目标站---无知用户---恶意站 http://fallensnow-jack.blogspot.com/2011/08/webgoat-csrf.html https://wiki.ca ...
- java 本地方法(JNI)
最近搞了一个调用第三方so库做登录认证的任务,以前对JNI没什么概念,最近学习了 <java核心技术> 本地方法 一章,把自己写的一些例子记录一下. 自己C语言真是渣渣,所以所有的例子都在 ...
- HBase的Write Ahead Log (WAL)
HBase的Write Ahead Log (WAL) 一.预写日志WAL(Write-Ahead-Log) HLog HLogKey LogFlusher LogRoller Replay 问题 二 ...
- centos编译安装vim7.4
./configure --with-features=huge --enable-fontset --enable-gui=gtk2 --enable-multibyte --enable-pyth ...
- 26.Apache
1.Apache简介 Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源代码的网页服务器软件,可以在大多数电脑操作系统中运行,由于其跨平台和安全性(尽管不断有 ...
- 数据中心网络技术新贵:VXLAN与园区网络虚拟化
摘要:为了应对传统数据中心网络对服务器虚拟化技术的限制,VXLAN技术应运而生. 1 概述 传统数据中心网络面临的问题 虚拟机规模受设备表项规格限制 在传统二层网络中,交换机通过查询MAC地址表来转发 ...
- 【机制】js的闭包、执行上下文、作用域链
1.从闭包说起 什么是闭包 一个函数和对其周围状态(词法环境)的引用捆绑在一起,这样的组合就是闭包. 也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域. 在 JavaScript 中,每 ...