hdu4348 为 心灵之旅To The Moon 出的 时光穿梭 题。主席树

91 阅读2分钟

摘自知乎:最后一刹那,心电检测仪发出永恒的线声,耳机传来主题曲,画面定格在美丽的月球,情绪被扯进澎湃的漩涡中,眼睛开始模糊时,我才明白:……

\

\

To the moon

**Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 5573    Accepted Submission(s): 1265
**
\

Problem Description

Background
To The Moon is a independent game released in November 2011, it is a role-playing adventure game powered by RPG Maker.
The premise of To The Moon is based around a technology that allows us to permanently reconstruct the memory on dying man. In this problem, we'll give you a chance, to implement the logic behind the scene.

You‘ve been given N integers A [1], A [2],..., A [N]. On these integers, you need to implement the following operations:
1. C l r d: Adding a constant d for every {A i | l <= i <= r}, and increase the time stamp by 1, this is the only operation that will cause the time stamp increase. 
2. Q l r: Querying the current sum of {A i | l <= i <= r}.
3. H l r t: Querying a history sum of {A i | l <= i <= r} in time t.
4. B t: Back to time t. And once you decide return to a past, you can never be access to a forward edition anymore.
.. N, M ≤ 10 5, |A [i]| ≤ 10 9, 1 ≤ l ≤ r ≤ N, |d| ≤ 10 4 .. the system start from time 0, and the first modification is in time 1, t ≥ 0, and won't introduce you to a future state.

 

\

Input

n m
A 1 A 2 ... A n
... (here following the m operations. )

 

\

Output

... (for each query, simply print the result. )

 

\

Sample Input

  
  

   
   10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

2 4
0 0
C 1 1 1
C 2 2 -1
Q 1 2
H 1 2 1
  
  

 

\

Sample Output

  
  

   
   4
55
9
15

0
1
  
  

 

\

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>
const int N = 1e5 + 7;
int T[N], tot, n, m;
int lson[N * 30], rson[N * 30], add[N * 30];
long long sum[N * 30];
inline void pushUp(int rt) {
	sum[rt] = sum[lson[rt]] + sum[rson[rt]];
}
int build(int l, int r) {
	int rt = tot++;
	add[rt] = 0;
	if (l == r) {
		scanf("%lld", sum + rt);
		return rt;
	}
	int mid = l + r >> 1;
	lson[rt] = build(l, mid);
	rson[rt] = build(mid + 1, r);
	pushUp(rt);
	return rt;
}
int update(int rt, int l, int r, int L, int R, int val) {
	int k = tot++; //k是新的根节点
	lson[k] = lson[rt]; rson[k] = rson[rt]; 
	add[k] = add[rt]; sum[k] = sum[rt];
	sum[k] += (long long)val * (R - L + 1);
	if (l == L && r == R) {
		add[k] += val; //修改延迟标记
		return k;
	}
	int mid = l + r >> 1;
	if (R <= mid) lson[k] = update(lson[k], l, mid, L, R, val);
	else if (L > mid) rson[k] = update(rson[k], mid + 1, r, L, R, val);
	else {
		lson[k] = update(lson[k], l, mid, L, mid, val);
		rson[k] = update(rson[k], mid + 1, r, mid + 1, R, val);
	}
	return k;
}
long long query(int rt, int l, int r, int L, int R) {
	if (l == L && r == R) return sum[rt];
	int mid = l + r >> 1;
	long long res = (long long)add[rt] * (R - L + 1);
	if (R <= mid)
		return res + query(lson[rt], l, mid, L, R);
	else if (L > mid)
		return res + query(rson[rt], mid + 1, r, L, R);
	else return res + query(lson[rt], l, mid, L, mid) 
		+ query(rson[rt], mid + 1, r, mid + 1, R); //注意这里
}
void init() {
	tot = 0;
	memset(sum, 0, sizeof sum);
	memset(add, 0, sizeof add);
	memset(T, 0, sizeof T);
}
int main()
{	
	while (~scanf("%d%d", &n, &m)) {
		int x, y, val, now = 0;
		char opt;
		init();
		T[0] = build(1, n);
		while (m-- > 0) {
			scanf(" %c", &opt);
			switch(opt) {
			case 'B':
				scanf("%d", &now);
				break;
			case 'H':
				scanf("%d%d%d", &x, &y, &val);
				printf("%lld\n", query(T[val], 1, n, x, y));
				break;
			case 'Q':
				scanf("%d%d", &x, &y);
				printf("%lld\n", query(T[now], 1, n, x, y));
				break;
			case 'C':
				scanf("%d%d%d", &x, &y, &val);
				++now; 
				T[now] = update(T[now - 1], 1, n, x, y, val);
				break;
			}
		}
	}

	return 0;
}




\

这道题我用普通的线段树离线操作没有解出来,可能不能用吧,时光穿梭到过去,会改变将来的

\

PS:这是国外自由鸟freebrid开发的,所以大家可能玩不成

\