法一:暴力!

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

但是空间好紧。怎么破?

不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. [转载] CMake Official Tutorial——教程还是官方的好

    CMake官方教程传送门:https://cmake.org/cmake-tutorial/ 以下的内容跟官方教程基本一致,少数地方根据自己的测试有所改动: A Basic Starting Poin ...

  2. Linux Bash环境下单引(')、双引号(")、反引号(`)、反斜杠(\)的小结

    在bash中,$.*.?.[.].’.”.`.\.有特殊的含义.类似于编译器的预编译过程,bash在扫描命令行的过程中,会在文本层次上,优先解释所有的特殊字符,之后对转换完成的新命令行,进行内核的系统 ...

  3. HDU1878欧拉回路

    这道题WA了好多次.测试数据感觉有点问题-- 并查集啊,必须有. #include<stdio.h> #include<string.h> int ad[1003]; int ...

  4. 我也来玩玩WinForm~BeginInvoke让用户体验更好!

    前言 先说明一下,本人不太做winform的项目,工作10年以来,一直奋斗在webform的舞台上,今天有机会也接触了一下winform,下面对工作中用到的BeginInvoke方法作一下说明,和大家 ...

  5. CSS3 中FLEX快速实现BorderLayout布局

    学习完flex的布局模式之后,我们趁热打铁,来实现一个BoxLayout布局.什么是BoxLayout布局?那我们先上一个图看看 BoxLayout布局写过后端UI代码的编程者应该不陌生了,写前端的代 ...

  6. ASP.NET中扩展FileUpload的上传文件的容量

    ASP.NET中扩展FileUpload只能上传小的文件,大小在4MB以内的.如果是上传大一点的图片类的可以在web.config里面扩展一下大小,代码如下 <system.web> &l ...

  7. jQuery提供的小方法

    jQuery提供的小方法: 1.选择器 + 事件 + 函数 = 复杂的交互 2.循环处理与选择器匹配的各个元素:each() $("#").each(function(){     ...

  8. Android内的生命周期整理

    1. Android App的生命周期: 2. Application的生命周期: 3. Activity的生命周期: 3.1 Fragment的生命周期: 4. Service的生命周期:5. Br ...

  9. mssql 获取表结构信息

    SELECT (case when a.colorder=1 then d.name else null end) 表名, a.colorder 字段序号,a.name 字段名, (case when ...

  10. gcc编译参数-fPIC问题 `a local symbol' can not be used when making a shared object;

    gcc -shared -o hack.so hack.c/usr/bin/ld: /tmp/ccUZREwA.o: relocation R_X86_64_32 against `a local s ...