法一:暴力!

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

但是空间好紧。怎么破?

不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. 【工具篇】source Insight

    不多说,阅读代码利器. 一.修改背景颜色 使用淡绿色更护眼(听说而已),菜单“选项”>>“属性”,使用自己喜欢的颜色吧.我的淡绿色RGB是181,236,207 二.行号,空格替换tabs ...

  2. php 连接mysql数据库并显示数据 实例 转载

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  3. 自定义QToolButton

    最近做界面需要添加很多工具栏按钮,所以自己定义了一个Button 直接上代码 SettingButton.cpp//设置Button的一些参数 #include "SettingButton ...

  4. 通过javascript实现页面的横竖屏固定

    javascript是不能固定页面是横屏还是竖屏的,但是我们可以通过另外一种思路来监听window.orientation状态,假设我们要固定页面为横屏显示,则当window.orientation返 ...

  5. python判断一个数字是整数还是浮点数

    在网上闲逛,发现了一个python的用法

  6. JNI-Test

    //testdll.h/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header fo ...

  7. C连接MySQL数据库开发之Windows环境配置及测试

    一.开发环境 Win8.1 64位.VS2013.MySQL5.5.3764位 MySQL安装目录为:C:\Program Files\MySQL\MySQL Server 5.5 二.配置工程环境 ...

  8. 写个自动安装JDK的shell脚本

    #!/bin/bash ################################################# # # INSTALL JDK AUTOMATICALLY # # auth ...

  9. bzoj 3505: [Cqoi2014]数三角形 组合数学

    3505: [Cqoi2014]数三角形 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 478  Solved: 293[Submit][Status ...

  10. bower的权限问题

    装bootstrap的时候,先用sudo指令装了bower,但是一打 bower isntall bootstrap 就报错: Error: EACCES, permission denied '/U ...