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

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

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

对于线段树上完全覆盖标记产生贡献的区间,我们直接打上一个$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. Ubuntu 16.04 NFS搭建

    NFS服务器配置: 1.安装NFS相关包 apt-get install nfs-kernel-server nfs-common # centos 7# yum install nfs-utils ...

  2. 也谈设计模式Facade

    门面模式提供一个高层次的接口,使得子系统更容易使用. 子系统与外部系统的通信必须经过一个统一的facade进行处理. 内部系统的交互在facade中进行整合,这样,对于外部系统的使用者就不用关注内部系 ...

  3. HDU 1533 Going home

    Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  4. Ogre的Singleton实现-模版实现,便于重用-(详细分析)以及笔者的改进

    转自:http://www.cppblog.com/sandy/archive/2005/11/30/1436.html ;Root g_root;//must declare once only / ...

  5. bzoj-1588 1588: [HNOI2002]营业额统计(BST)

    题目链接: 1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 13596  Solved: 5049[Submi ...

  6. RouterOS(ROS)简单限速/单IP限速脚

    暂无评论 有时企业环境,或个人使用环境需要针对不同IP设置较多条不同限速,可以使用以下脚本批量处理后,再针对性的修改. *脚本说明:“2 to 254”定义要设置受限IP的起始,后面“192.168. ...

  7. Python语言及其应用 第2章

  8. Ffmpeg转码研究一

    Ffmpeg是一款功能强大的视频处理工具,那么转码肯定不是问题的,因为项目的需求,对转码进行了研究.刚开始首先去看了ffmpeg源代码中的一个例子transcode.c,但是发现该例子更应该称之为re ...

  9. ACM学习历程—HDU5423 Rikka with Tree(搜索)

    Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, so he ...

  10. 浏览器全屏的JS代码实现

    方法一:该方法是从一个网上的效果看到不错,然后自己就拿来下来实验了一下,还是比较满意度,下面直接给出代码 <!DOCTYPE HTML> <html lang="en-US ...