hdu4348 - To the moon 可持久化线段树 区间修改 离线处理
法一:暴力!
让干什么就干什么,那么久需要可持久化线段树了。
但是空间好紧。怎么破?
不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 可持久化线段树 区间修改 离线处理的更多相关文章
- 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 ...
- hdu4348 To the moon (可持久化线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4348 题目大意:给定含有n个数的序列,有以下四种操作 1.C l r d:表示对区间[l,r]中的数加 ...
- 计蒜客 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 ...
- 【bzoj2653】middle 可持久化线段树区间合并
题目描述 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[ ...
- 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序加上一个线 ...
- 题解报告: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 ...
- poj 2528 线段树区间修改+离散化
Mayor's posters POJ 2528 传送门 线段树区间修改加离散化 #include <cstdio> #include <iostream> #include ...
- HDU 4348 To the moon 可持久化线段树,有时间戳的区间更新,区间求和
To the moonTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.a ...
- HDU 4417.Super Mario-可持久化线段树(无修改区间小于等于H的数的个数)
Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
随机推荐
- 【转】oracle数据库NUMBER数据类型
原文:http://www.jb51.net/article/37633.htm NUMBER ( precision, scale)a) precision表示数字中的有效位;如果没有指定prec ...
- [Linux]Ubuntu下如何将普通用户提升到root权限
转至:http://jingyan.baidu.com/album/6181c3e0780131152ef153ff.html?picindex=0&qq-pf-to=pcqq.c2c 在u ...
- 让chrome浏览器快的不要不要的
Chrome 已经成了很多人的主力浏览器,你可能被它的简洁快速所吸引,但它日益丰富的「扩展」,你可能从来都没有接触过,而事实上,很多扩展可以挖掘出 Chrome 的潜能,让它变得前所未有的强大.有哪些 ...
- MacOS 下端口占用解决办法
现象:Mac下,IDEA正常关闭tomcat时,仍旧抛出8009 端口被占用. 解决: 1. 终端(命令行)上,输入命令 lsof -i tcp: 2. 找到这个进程的 PID,好吧,kill掉它 k ...
- BZOJ 4052 Magical GCD
Description 给出一个长度在\(100000\)以内的正整数序列,大小不超过\(10^{12}\).求一个连续子序列,使得在所有的连续子序列中,它们的GCD值乘以它们的长度最大. Input ...
- [BZOJ 2186] [Sdoi2008] 沙拉公主的困惑 【欧拉函数】
题目链接:BZOJ - 2186 题目分析 题目要求出 [1, n!] 中有多少数与 m! 互质.(m <= n) 那么在 [1, m!] 中有 phi(m!) 个数与 m! 互质,如果一个数 ...
- 【Tools】maven安装
安装Maven插件老是报以下的错误,好像少了一个叫guava库的东西,但是在其他机器安装不报这个错误. Cannot complete the install because one or more ...
- Android 通过开源框架AsyncHttpClient进行get和post请求
使用时无需将这些代码放入子线程去执行,因为其内部已经封装到一个线程中运行了! public void asyncHttpClientGet(View view) { AsyncHttpClient c ...
- 【HDU3948】 The Number of Palindromes (后缀数组+RMQ)
The Number of Palindromes Problem Description Now, you are given a string S. We want to know how man ...
- js页面传参数时,参数值包含特殊字符的处理
js页面传参数时,参数值包含特殊字符应该怎么处理,解决方法就是利用js的escape函数,这个函数在解决中文乱码等方面应用的比较广泛.推荐使用. 工作中遇到的小问题,一个页面中通过window.sho ...