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

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

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

对于线段树上完全覆盖标记产生贡献的区间,我们直接打上一个$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. [原创]java WEB学习笔记37:EL表达式(简介,运算符,自动类型转换,保留字,隐含对象)

    1.EL 简介 1)EL 全名为 Expression  Language,它原本是 JSTL  1.0 为方便存取数据所自定义的语言 2)语法:EL 语法很简单,它最大的特点就是使用上很方便:${s ...

  2. 第五章 python中的异常处理

    每种编程语言都会有自己的异常处理机制,虽然各有特色,但基本上都差不多,那么python中强大异常处理机制是什么样的呢? 一.异常: python用异常对象来表示异常情况,遇到错误后,会引发异常.如果异 ...

  3. POJ 1068 Parencodings (类似括号的处理问题)

                                                                                                    Pare ...

  4. RabbitMQ之Exchange Topics模式

    说明:此模式实在路由key模式的基础上,使用了通配符来管理消费者接收消息.生产者P发送消息到交换机X,type=topic,交换机根据绑定队列的routing key的值进行通配符匹配: 符号#:匹配 ...

  5. 图文了解 Kafka 的副本复制机制

    让分布式系统的操作变得简单,在某种程度上是一种艺术,通常这种实现都是从大量的实践中总结得到的.Apache Kafka 的受欢迎程度在很大程度上归功于其设计和操作简单性.随着社区添加更多功能,开发者们 ...

  6. Future模式实例

    Future模式 /** * qccr.com Inc. * Copyright (c) 2014-2016 All Rights Reserved. */ package com.youqianhu ...

  7. python自动化开发学习 I/O多路复用

    python自动化开发学习 I/O多路复用   一. 简介 socketserver在内部是由I/O多路复用,多线程和多进程,实现了并发通信.IO多路复用的系统消耗很小. IO多路复用底层就是监听so ...

  8. Linux-tcpdump command

    简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据包的 ...

  9. PyQt5布局管理(1)

    Qt布局管理按简单分可分为绝对位置布局和布局管理器布局 一.绝对位置布局: 组件不放在布局管理器中,通过函数setGeometry(x,y,width,height)来设定组件相对其父窗口的位置.其中 ...

  10. STL stl_alloc.h

    # // Comment By: 凝霜 # // E-mail: mdl2009@vip.qq.com # // Blog: http://blog.csdn.net/mdl13412 # # // ...