法一:暴力!

让干什么就干什么,那么久需要可持久化线段树了。

但是空间好紧。怎么破?

不down标记好了!

每个点维护sum和add两个信息,sum是这段真实的和,add是这段整体加了多少,如果这段区间被完全包含,返回sum,否则加上add * 询问落在这段区间的长度再递归回答。

怎么还是MLE?

麻辣鸡指针好像8字节,所以改成数组的就过了。。。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream> using namespace std; template<typename Q> Q &read(Q &x) {
static char c, f;
for(f = ; c = getchar(), !isdigit(c); ) if(c == '-') f = ;
for(x = ; isdigit(c); c = getchar()) x = x * + c - '';
if(f) x = -x; return x;
}
template<typename Q> Q read() {
static Q x; read(x); return x;
} typedef long long LL;
const int N = + ;
struct Node *pis;
struct Node {
LL sum, add;
Node *ch[]; Node *modify(int l, int r, int L, int R, LL d) {
Node *o = new Node(*this);
if(L <= l && r <= R) {
o->add += d;
o->sum += (r - l + ) * d;
return o;
}
int mid = (l + r) >> ;
if(L <= mid) o->ch[] = ch[]->modify(l, mid, L, R, d);
if(mid < R) o->ch[] = ch[]->modify(mid + , r, L, R, d);
o->sum = o->ch[]->sum + o->ch[]->sum + o->add * (r - l + );
return o;
} LL query(int l, int r, int L, int R) {
if(L <= l && r <= R) return sum;
int mid = (l + r) >> ;
LL res = (min(R, r) - max(L, l) + ) * add;
if(L <= mid) res += ch[]->query(l, mid, L, R);
if(mid < R) res += ch[]->query(mid + , r, L, R);
return res;
} void *operator new(size_t) {
return pis++;
}
}pool[ + ], *root[N]; void build(Node *&o, int l, int r) {
o = new Node, o->add = ;
if(l == r) return read(o->sum), void();
int mid = (l + r) >> ;
build(o->ch[], l, mid);
build(o->ch[], mid + , r);
o->sum = o->ch[]->sum + o->ch[]->sum;
} int main() {
#ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif int n, m, cur;
char opt[];
while(scanf("%d%d", &n, &m) == ) {
cur = , pis = pool;
build(root[cur], , n);
while(m--) {
if(m == ) {
int debug = ;
}
scanf("%s", opt);
if(opt[] == 'C') {
int l, r; LL d;
read(l), read(r), read(d);
root[cur + ] = root[cur]->modify(, n, l, r, d);
cur++;
}else if(opt[] == 'Q') {
int l, r; read(l), read(r);
printf("%I64d\n", root[cur]->query(, n, l, r));
}else if(opt[] == 'H') {
int l, r, t; read(l), read(r), read(t);
printf("%I64d\n", root[t]->query(, n, l, r));
}else read(cur);
}
puts("");
} return ;
}

指针版

 #include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream> using namespace std; template<typename Q> Q &read(Q &x) {
static char c, f;
for(f = ; c = getchar(), !isdigit(c); ) if(c == '-') f = ;
for(x = ; isdigit(c); c = getchar()) x = x * + c - '';
if(f) x = -x; return x;
}
template<typename Q> Q read() {
static Q x; read(x); return x;
} typedef long long LL;
const int N = + ; int ch[N][], tot, root[N];
LL sum[N], add[N]; int modify(int s, int l, int r, int L, int R, LL d) {
int x = tot++;
sum[x] = sum[s];
add[x] = add[s];
ch[x][] = ch[s][];
ch[x][] = ch[s][]; if(L <= l && r <= R) {
add[x] += d;
sum[x] += (r - l + ) * d;
}else {
int mid = (l + r) >> ;
if(L <= mid) ch[x][] = modify(ch[s][], l, mid, L, R, d);
if(mid < R) ch[x][] = modify(ch[s][], mid + , r, L, R, d);
sum[x] = sum[ch[x][]] + sum[ch[x][]] + add[x] * (r - l + );
}
return x;
} LL query(int s, int l, int r, int L, int R) {
if(L <= l && r <= R) return sum[s];
int mid = (l + r) >> ;
LL res = (min(R, r) - max(L, l) + ) * add[s];
if(L <= mid) res += query(ch[s][], l, mid, L, R);
if(mid < R) res += query(ch[s][], mid + , r, L, R);
return res;
} void build(int &s, int l, int r) {
s = tot++, add[s] = ;
if(l == r) return read(sum[s]), void();
int mid = (l + r) >> ;
build(ch[s][], l, mid);
build(ch[s][], mid + , r);
sum[s] = sum[ch[s][]] + sum[ch[s][]];
} int main() {
#ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif int n, m, cur;
char opt[];
while(scanf("%d%d", &n, &m) == ) {
cur = tot = ;
build(root[cur], , n);
while(m--) {
if(m == ) {
int debug = ;
}
scanf("%s", opt);
if(opt[] == 'C') {
int l, r; LL d;
read(l), read(r), read(d);
root[cur + ] = modify(root[cur], , n, l, r, d);
cur++;
}else if(opt[] == 'Q') {
int l, r; read(l), read(r);
printf("%I64d\n", query(root[cur], , n, l, r));
}else if(opt[] == 'H') {
int l, r, t; read(l), read(r), read(t);
printf("%I64d\n", query(root[t], , n, l, r));
}else read(cur);
}
// puts("");
} return ;
}

数组版

法二:离线!

主要需要处理H操作。

在第一遍读入数据的时候维护一个pos[]数组,表示当前第i个版本是由pos[i]这个C操作创建的。

然后碰到H就把它挂在pos[t]上就可以,第二遍处理的时候直接回答。

 #include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream> using namespace std; template<typename Q> Q &read(Q &x) {
static char c, f;
for(f = ; c = getchar(), !isdigit(c); ) if(c == '-') f = ;
for(x = ; isdigit(c); c = getchar()) x = x * + c - '';
if(f) x = -x; return x;
}
template<typename Q> Q read() {
static Q x; read(x); return x;
} typedef long long LL;
const int N = + ; int n, m;
class SegementTree {
private:
LL sum[N * ], tag[N * ]; #define mid ((l + r) >> 1)
#define ls s << 1, l, mid
#define rs s << 1 | 1, mid + 1, r void add_tag(int s, int l, int r, LL d) {
tag[s] += d;
sum[s] += (r - l + ) * d;
} void down(int s, int l, int r) {
if(tag[s]) {
add_tag(ls, tag[s]);
add_tag(rs, tag[s]);
tag[s] = ;
}
} int lft, rgt;
LL w; void modify(int s, int l, int r) {
if(lft <= l && r <= rgt) return add_tag(s, l, r, w);
down(s, l, r);
if(lft <= mid) modify(ls);
if(mid < rgt) modify(rs);
sum[s] = sum[s << ] + sum[s << | ];
} LL query(int s, int l, int r) {
if(lft <= l && r <= rgt) return sum[s];
down(s, l, r);
if(rgt <= mid) return query(ls);
if(mid < lft) return query(rs);
return query(ls) + query(rs);
} public:
void build(int s, int l, int r) {
tag[s] = ;
if(l == r) return read(sum[s]), void();
build(ls), build(rs);
sum[s] = sum[s << ] + sum[s << | ];
}
#undef mid
#undef ls
#undef rs void Modify(int l, int r, LL w) {
lft = l, rgt = r, this->w = w;
modify(, , n);
}
LL Query(int l, int r) {
lft = l, rgt = r;
return query(, , n);
}
}seg; struct operation {
char tp;
int l, r;
LL d;
}opt[N]; #include<stack>
stack<int> stk; #include<vector>
vector<int> G[N]; int pos[N];
LL ans[N]; int main() {
#ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif char s[];
while(scanf("%d%d", &n, &m) == ) {
seg.build(, , n);
int cur = ;
for(int i = ; i < m; i++) {
scanf("%s", s);
opt[i].tp = s[];
if(s[] == 'C') {
read(opt[i].l), read(opt[i].r), read(opt[i].d);
pos[++cur] = i;
}else if(s[] == 'Q') {
read(opt[i].l), read(opt[i].r);
}else if(s[] == 'H') {
read(opt[i].l), read(opt[i].r), read(opt[i].d);
if(!opt[i].d) ans[i] = seg.Query(opt[i].l, opt[i].r);
else G[pos[opt[i].d]].push_back(i);
}else cur = read(opt[i].d);
} cur = ;
for(int i = ; i < m; i++) {
if(opt[i].tp == 'C') {
seg.Modify(opt[i].l, opt[i].r, opt[i].d);
for(unsigned j = ; j < G[i].size(); j++) {
int k = G[i][j];
ans[k] = seg.Query(opt[k].l, opt[k].r);
}
++cur;
stk.push(i);
}else if(opt[i].tp == 'Q') {
ans[i] = seg.Query(opt[i].l, opt[i].r);
}else if(opt[i].tp == 'B') {
while(cur > opt[i].d) {
int k = stk.top(); stk.pop();
seg.Modify(opt[k].l, opt[k].r, -opt[k].d);
cur--;
}
}
} for(int i = ; i < m; i++) {
if(opt[i].tp == 'Q' || opt[i].tp == 'H') {
printf("%I64d\n", ans[i]);
}
}
} return ;
}

离线版

hdu4348 - To the moon 可持久化线段树 区间修改 离线处理的更多相关文章

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

  2. hdu4348 To the moon (可持久化线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4348 题目大意:给定含有n个数的序列,有以下四种操作 1.C l r d:表示对区间[l,r]中的数加 ...

  3. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  4. 【bzoj2653】middle 可持久化线段树区间合并

    题目描述 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[ ...

  5. Codeforces Round #442 (Div. 2) E Danil and a Part-time Job (dfs序加上一个线段树区间修改查询)

    题意: 给出一个具有N个点的树,现在给出两种操作: 1.get x,表示询问以x作为根的子树中,1的个数. 2.pow x,表示将以x作为根的子树全部翻转(0变1,1变0). 思路:dfs序加上一个线 ...

  6. 题解报告:hdu 1698 Just a Hook(线段树区间修改+lazy懒标记的运用)

    Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing for m ...

  7. poj 2528 线段树区间修改+离散化

    Mayor's posters POJ 2528 传送门 线段树区间修改加离散化 #include <cstdio> #include <iostream> #include ...

  8. HDU 4348 To the moon 可持久化线段树,有时间戳的区间更新,区间求和

    To the moonTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.a ...

  9. HDU 4417.Super Mario-可持久化线段树(无修改区间小于等于H的数的个数)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

随机推荐

  1. QT UI 使一个QWidget里面的元素自动填充满本QWidget

    使一个QWidget里面的元素自动填充满本QWidget: 对象查看器,右键点击本QWidget,选择"布局",为此QWidget增加一个布局. 如果该QWidget只有一个对象, ...

  2. MATLAB中的函数的归总

    字符串操作函数 1.        函数eval可以用来执行用字符串表示的表达式 2.        函数deblank可以去掉字符串末尾的所有空格 3.        函数findstr可以用来在长 ...

  3. C++ trivial和non-trivial构造函数及POD类型(转)

    原博客地址http://blog.csdn.net/a627088424/article/details/48595525 最近正纠结这个问题就转过来了,做了点补充(参考<深度探索C++对象模型 ...

  4. 由C到C++的学习 ----Essential C++

    一.array[] 与 vector<int> vector1 1 array[] <- 此中要填写数组的大小,而且array[]自己是不知道自己的大小的 2.1 vector< ...

  5. C++单元测试2

    这里再对上一篇<C++单元测试>进行技巧补充. 我们知道对动态链接库(lib和dll)的测试是比较简单的,我这里主要对需要注意的地方说明一下. 1.建议单独创建单元测试解决方案(不是创建项 ...

  6. ACM YTU 2018 母牛的故事

    母牛的故事 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  7. 设计模式之 Singleton 单例模式

    先上两段代码,区别仅在于是否涉及线程安全. 首先是不涉及多线程的单例: public class Singleton { private final static Singleton INSTANCE ...

  8. 网页解析Jsoup简单使用

    public static void main(String[] args) throws IOException { //System.out.println("Hello World!& ...

  9. Python 学习之urllib模块---用于发送网络请求,获取数据

    1.urllib urllib是Python标准库的一部分,包含urllib.request,urllib.error,urllib.parse,urlli.robotparser四个子模块. (1) ...

  10. bitVector@ java bit自我practice##Q&A:为何int 来初始化size of bitVector?long,甚至是BigInteger等策略

    /* * BitSets are packed into arrays of "words." Currently a word is * a long, which consis ...