SPOJ-TTM To the moon
一句话题意:写一个支持区间修改,区间求和的可持久化数据结构。
考虑使用主席树,然而,区间修改怎么办?
似乎有标记永久化的方法。
对于线段树上完全覆盖标记产生贡献的区间,我们直接打上一个$tag$,而对于不完全产生贡献但是会产生贡献的区间,我们直接把贡献累加到$sum$里面去。
查询的时候从上往下走一走,顺便算一算这个结点的$tag$会对答案产生多少贡献。
我们知道任何一条线段(长度为$n$)会被拆成不超过$logn$级别的小的长度为$2^k$长的线段,这样子我们每一次修改新建的结点也是$log$级别的。
并不会算空间。尽量开大。
时间复杂度当然是$O((n + m)logn)$。
Code:
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll; const int N = 1e5 + ; int n, qn;
ll a[N]; template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline int max(int x, int y) {
return x > y ? x : y;
} inline int min(int x, int y) {
return x > y ? y : x;
} namespace PSegT {
struct Node {
int lc, rc;
ll sum, tag;
} s[N * ]; int root[N], nodeCnt = ; #define lc(p) s[p].lc
#define rc(p) s[p].rc
#define sum(p) s[p].sum
#define tag(p) s[p].tag
#define mid ((l + r) >> 1) inline void up(int p) {
if(p) sum(p) = sum(lc(p)) + sum(rc(p));
} void build(int &p, int l, int r) {
p = ++nodeCnt, tag(p) = 0LL;
if(l == r) {
sum(p) = a[l];
return;
} build(lc(p), l, mid);
build(rc(p), mid + , r);
up(p);
} void modify(int &p, int l, int r, int x, int y, ll v, int pre) {
s[p = ++nodeCnt] = s[pre];
if(x <= l && y >= r) {
tag(p) += 1LL * v;
return;
} else {
int len = min(r, y) - max(l, x) + ;
sum(p) += 1LL * len * v;
} if(x <= mid) modify(lc(p), l, mid, x, y, v, lc(pre));
if(y > mid) modify(rc(p), mid + , r, x, y, v, rc(pre));
} ll query(int p, int l, int r, int x, int y) {
if(x <= l && y >= r) return sum(p) + 1LL * (r - l + ) * tag(p); int len = min(r, y) - max(l, x) + ;
ll res = 1LL * len * tag(p); if(x <= mid) res += query(lc(p), l, mid, x, y);
if(y > mid) res += query(rc(p), mid + , r, x, y);
return res;
} } using namespace PSegT; int main() {
// freopen("Sample.txt", "r", stdin); for(; scanf("%d%d", &n, &qn) != EOF; ) {
// read(n), read(qn);
for(int i = ; i <= n; i++) read(a[i]); memset(root, , sizeof(root)); nodeCnt = ;
int now = ;
build(root[], , n); /* for(int i = 1; i <= n; i++)
printf("%lld ", query(root[0], 1, n, i, i));
printf("\n"); */ for(int i = ; i <= qn; i++) {
char op[];
scanf("%s", op);
if(op[] == 'C') {
int x, y; read(x), read(y);
ll v; read(v);
++now;
modify(root[now], , n, x, y, v, root[now - ]);
}
if(op[] == 'Q') {
int x, y; read(x), read(y);
printf("%lld\n", query(root[now], , n, x, y));
}
if(op[] == 'H') {
int x, y, t; read(x), read(y), read(t);
printf("%lld\n", query(root[t], , n, x, y));
}
if(op[] == 'B') {
int t; read(t);
for(int j = t + ; j <= now; j++) root[j] = ;
now = t;
}
} /* for(int t = 0; t <= tim; t++, printf("\n"))
for(int i = 1; i <= n; i++)
printf("%lld ", query(root[t], 1, n, 1, 2)); */ // printf("\n"); for(int i = ; i <= nodeCnt; i++)
lc(i) = rc(i) = sum(i) = tag(i) = 0LL;
} return ;
}
SPOJ-TTM To the moon的更多相关文章
- 2018.08.04 spoj TTM to the moon(主席树)
spoj传送门 vjudge传送门 主席树板子题. 支持历史版本的区间和,区间和,区间修改和时光倒流. 其中新奇一点的也只有区间修改了,这个东西直接标记永久化就行了. 如果想下传标记的话也行,需要在p ...
- HDU 4348.To the moon SPOJ - TTM To the moon -可持久化线段树(带修改在线区间更新(增减)、区间求和、查询历史版本、回退到历史版本、延时标记不下放(空间优化))
To the moon Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- SP11470 TTM - To the moon[主席树标记永久化]
SP11470 TTM - To the moon C l r d:区间 \([L,R]\) 中的数都加 d ,同时当前的时间戳加 1. Q l r:查询当前时间戳区间 \([L,R]\) 中所有数的 ...
- 「SPOJ TTM 」To the moon「标记永久化」
题意 概括为主席树区间加区间询问 题解 记录一下标记永久化的方法.每个点存add和sum两个标记,表示这个区间整个加多少,区间和是多少(这个区间和不包括祖先结点区间加) 然后区间加的时候,给路上每结点 ...
- HDU 4348 SPOJ 11470 To the moon
Vjudge题面 Time limit 2000 ms Memory limit 65536 kB OS Windows Source 2012 Multi-University Training C ...
- SPOJ - TTM 主席树
给你一个系列\(a[1...n]\),要求可以区间求和,区间更新,也可以回溯过去 经典的主席树板子题,很久以前做的题了,代码太丑回炉重写 PS.题目标题To The Moon也是我最喜欢的游戏之一 这 ...
- SPOJ:To the moon
题面 vjudge Sol 主席树模板 # include <bits/stdc++.h> # define RG register # define IL inline # define ...
- SP11470 TTM - To the moon
嘟嘟嘟 主席树+区间修改. 以为是水题,写着写着发现区间修改标记下传会出问题,然后想了想发现以前做的只是单点修改. 那怎么办咧? 然后题解交了我标记永久化这个神奇的东西. 特别好理解,就是修改的时候直 ...
- 「SP11470」TTM - To the moon
题目描述 给定一段长度为 \(N\) 的序列 \(a\) 以及 \(M\) 次操作,操作有以下几种: C l r d :将区间 \([l,r]\) 中的数都加上 \(d\) Q l r :查询当前时间 ...
- 洛谷——P3919 【模板】可持久化数组(可持久化线段树/平衡树)
P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目背景 UPDATE : 最后一个点时间空间已经放大 标题即题意 有了可持久化数组,便可以实现很多衍生的可持久化功能(例如:可持久化并查集 ...
随机推荐
- 第三章 python中的字符串
一.字符串的基本操作 所有标准的序列操作对字符串同样适用,如索引.分片.乘法.判断成员是否存在.求长度.最大值和最小值等.记住一点,字符串是不可变的. 二.字符串中重要的方法 1.find(subst ...
- MySQL的进程状态
通过show processlist查看MySQL的进程状态,在State列上面的状态有如下这些: Analyzing线程对MyISAM 表的统计信息做分析(例如, ANALYZE TABLE ).c ...
- Linux 基本命令总结
0.平时自己用的命令 在跑一些程序,例如deep learning的时候,总是希望查看一下cpu.gpu.内存的使用率. (1)cpu.内存情况:使用top命令: (2)查看gpu:使用 nvidia ...
- 2013面试C++小结
2013年我在厦门c++求职小结 1.一般公司出的面试题目中的找错误,都是出自平常公司内部使用过程中出现的真实错误. 比如stl 中erase的使用:详细请见 :http://blog.csdn.ne ...
- JavaUtil_09_通用工具类-01_Hutool
一.重要的官方资料 1. Hutool 官网 2. Hutool 参考文档 3. Hutool API文档
- js事件绑定的几种方式与on()、bind()的区别
版权声明:本文为博主原创文章,未经博主允许不得转载 一直不是很理解几种js事件绑定之间的区别与联系,今天百度了一下,在此做一总结: 1.如果只是简单的绑定一个事件,可以直接写在行内,点击执行一个函数, ...
- OPcache
1.介绍 OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能, 存储预编译字节码的好处就是 省去了每次加载和解析 PHP 脚本的开销 2.配置 2.1 opcac ...
- SSH Secure Shell 的使用
一,安装Secure Shell ,之后会出现SSH Secure Shell client 和SSH Secure File Transfer client 两个快捷方式. 需要服务器的IP地址,用 ...
- JDBC获得数据库连接及使用
1.Connection Java.sql.Driver 接口是所有 JDBC 驱动程序需要实现的接口.这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现 在程序中不需要直接去访问实现了 ...
- shader学习推荐
<DirectX 9.0 3D游戏开发编程基础> 当您理解了如何实现顶点着色器和像素着色器之后,接下来您可能想进一步了解使用这两种着色器能够实现哪些效果. 最好的方式就是研究一下现有的各种 ...