一句话题意:写一个支持区间修改,区间求和的可持久化数据结构。

考虑使用主席树,然而,区间修改怎么办?

似乎有标记永久化的方法。

对于线段树上完全覆盖标记产生贡献的区间,我们直接打上一个$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的更多相关文章

  1. 2018.08.04 spoj TTM to the moon(主席树)

    spoj传送门 vjudge传送门 主席树板子题. 支持历史版本的区间和,区间和,区间修改和时光倒流. 其中新奇一点的也只有区间修改了,这个东西直接标记永久化就行了. 如果想下传标记的话也行,需要在p ...

  2. 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 ...

  3. SP11470 TTM - To the moon[主席树标记永久化]

    SP11470 TTM - To the moon C l r d:区间 \([L,R]\) 中的数都加 d ,同时当前的时间戳加 1. Q l r:查询当前时间戳区间 \([L,R]\) 中所有数的 ...

  4. 「SPOJ TTM 」To the moon「标记永久化」

    题意 概括为主席树区间加区间询问 题解 记录一下标记永久化的方法.每个点存add和sum两个标记,表示这个区间整个加多少,区间和是多少(这个区间和不包括祖先结点区间加) 然后区间加的时候,给路上每结点 ...

  5. HDU 4348 SPOJ 11470 To the moon

    Vjudge题面 Time limit 2000 ms Memory limit 65536 kB OS Windows Source 2012 Multi-University Training C ...

  6. SPOJ - TTM 主席树

    给你一个系列\(a[1...n]\),要求可以区间求和,区间更新,也可以回溯过去 经典的主席树板子题,很久以前做的题了,代码太丑回炉重写 PS.题目标题To The Moon也是我最喜欢的游戏之一 这 ...

  7. SPOJ:To the moon

    题面 vjudge Sol 主席树模板 # include <bits/stdc++.h> # define RG register # define IL inline # define ...

  8. SP11470 TTM - To the moon

    嘟嘟嘟 主席树+区间修改. 以为是水题,写着写着发现区间修改标记下传会出问题,然后想了想发现以前做的只是单点修改. 那怎么办咧? 然后题解交了我标记永久化这个神奇的东西. 特别好理解,就是修改的时候直 ...

  9. 「SP11470」TTM - To the moon

    题目描述 给定一段长度为 \(N\) 的序列 \(a\) 以及 \(M\) 次操作,操作有以下几种: C l r d :将区间 \([l,r]\) 中的数都加上 \(d\) Q l r :查询当前时间 ...

  10. 洛谷——P3919 【模板】可持久化数组(可持久化线段树/平衡树)

    P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目背景 UPDATE : 最后一个点时间空间已经放大 标题即题意 有了可持久化数组,便可以实现很多衍生的可持久化功能(例如:可持久化并查集 ...

随机推荐

  1. STM32 JTDO JREST复用为普通IO

    一.开启AFIO的时钟(必须保证先打开AFIO,否则无效) RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 二.禁用JTAG,使能SWD GP ...

  2. P4240 毒瘤之神的考验

    题目 P4240 毒瘤之神的考验 神仙题\(emmm\) 前置 首先有一个很神奇的性质: \(\varphi(ij)=\dfrac{\varphi(i)\varphi(j)gcd(i,j)}{\var ...

  3. rail模型

    rail是一种以用户为中心的性能模型,又google提出,其主要目标是让用户满意,主要分为response animation idle load四个部分 response 输入延迟时间小于100毫秒 ...

  4. Google员工自述:在哈佛教书和在Google工作的差别

    感谢伯乐在线的投递编者按:2003年到2010年期间,原文作者Matt Welsh 是哈佛大学工程和应用科学学院的计算机科学系教授.2010年加入Google,是一名高级工程师.他当前的工作重点是广域 ...

  5. Linux初识(命令, 文件, 系统管理)

    Linux初识(命令, 文件) 文件系统 在Linux系统下,没有驱动器磁盘,只有一个根目录 / ,所有的文件都在根目录下面. 相关文件夹介绍 bin : 程序相关 boot : 开机启动相关 cdr ...

  6. 分享知识-快乐自己:Liunx 安装 Zookeeper

    Zookeeper可以安装在windows中也可以安装在linux中! 但是我们的服务器基本都是在linux之上 安装我们的 zookeeper 注册中心! 安装成功之后  修改 nat 模式对应的端 ...

  7. Mysql存储过程及调用

     存储过程: 存储过程是SQL 语句和可选控制流语句的预编译集合,以一个名称存储并作为一个单元处理.存储过程存储在数据库内,可由应用程序通过一个调用执行,而且允许用户声明变量.有条件执行以及其它强大的 ...

  8. linux-常用指令3

    系统管理命令 stat              显示指定文件的详细信息,比ls更详细 who               显示在线登陆用户 whoami          显示当前操作用户 host ...

  9. Java--异常与字符串

    1.处理异常 try-catch以及try-catch-finally try{ //一些会抛出的异常 }catch(Exception e){ //处理该异常的代码块 }catch(Exceptio ...

  10. codeforces 633B B. A Trivial Problem(数论)

    B. A Trivial Problem time limit per test 2 seconds memory limit per test 256 megabytes input standar ...