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

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

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

对于线段树上完全覆盖标记产生贡献的区间,我们直接打上一个$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. nodejs模块之event

    event模块是nodejs系统中十分重要的一个模块,使用该模块我们可以实现事件的绑定的触发,为什么我们需要这个模块呢,因为nodejs是单线程异步的. 一.什么是单线程异步: 我们可以从JavaSc ...

  2. Redis高级进阶(一)

    一.redis中的事务 在关系型数据库中事务是必不可少的一个核心功能,生活中也是处处可见,比如我们去银行转账,首先需要将A账户的钱划走,然后存到B账户上,这两个步骤必须在同一事务中,要么都执行,要么都 ...

  3. django配置文件环境分离后celery的启动方式整理

    django项目中,当配置文件分离时: 启动方式1: 硬编码写死在manage.py中: os.environ.setdefault("DJANGO_SETTINGS_MODULE" ...

  4. UIView的概念与使用

    什么是UIView UIView可以称之为控件/视图 屏幕上所有能看到的东西都是UIView 按钮(UIButton).文本(UILabel)都是控件 控件都有一些共同的属性 -- 尺寸 -- 位置 ...

  5. DB2常见错误

    +098 01568 动态SQL语句用分号结束+100 02000 没有找到满足SQL语句的行+110 01561 用DATA CAPTURE定义的表的更新操作不能发送到原来的子系统+111 0159 ...

  6. EntityFramework 学习 一 Spatial Data type support in Entity Framework 5.0

    MS SQl Server引进两种特殊的数据类型geography and geometry public partial class Course { public Course() { this. ...

  7. 自顶向下归并排序(Merge Sort)

    一.自顶向下的归并排序思路: 1.先把数组分为两个部分. 2.分别对这两个部分进行排序. 3.排序完之后,将这两个数组归并为一个有序的数组. 重复1-3步骤,直到数组的大小为1,则直接返回. 这个思路 ...

  8. Spark持久化策略

    spark持久化策略_缓存优化persist.cache都是持久化到内存缓存策略 StorageLevel_useDisk:是否使用磁盘_useMemory:是否使用内存_useOffHeap:不用堆 ...

  9. HTML5调用百度地图API进行地理定位实例

    自从HTML5的标准确定以后,越来越多的网站使用HTML5来进行开发.虽然对HTML5支持的浏览器不是很多,但是依然抵挡不了大伙对HTML5开发的热情.今天为大家带来的是使用HTML5调用百度地图AP ...

  10. priority_queue用法(转载)

    关于priority_queue 1,关于STL中的priority_queue:确定用top()查看顶部元素时,该元素是具有最高优先级的一个元素. 调用pop()删除之后,将促使下一个元素进入该位置 ...