HDU-4348 To the moon
本文采用中英文版本结合。/This article adopts a combination of Chinese and English versions.
The English version
A glance at the Persistent Segment Tree.
Main Idea of the Question
Given a sequence, there are 4 operations:
C l r d: This operation adds a numberdto the interval[l, r]and increments the time by 1.Q l r: This operation queries the sum of the interval[l, r]at the current time.H l r t: This operation queries the sum of the interval[l, r]at timet.B t: This operation goes back to timet. All future states are invalidated.
Solution
Seeing that there is version rollback, consider using a Persistent Segment Tree.
The first operation is actually to create a new version and then perform interval modification.
The second operation is simply to query the sum maintained by the interval.
The third operation is to query the sum maintained by the interval in version \(t\).
The fourth operation is just to directly change the current version to the target version.
中文版
一眼主席树。
题目大意
给出一个序列,有 \(4\) 个操作:
C l r d:表示将区间 \([l,r]\) 加上一个数 \(d\),并将时间加 \(1\)。Q l r:表示询问当前时间区间 \([l,r]\) 的区间和。H l r t:表示询问在时间 \(t\) 的时候区间 \([l,r]\) 的区间和。B t:表示回到时间 \(t\)。之后未来的状态作废。
解法
看到有版本回溯,考虑主席树。
第一个操作其实就是新建一个版本,然后做区间修改。
第二个操作就直接询问区间维护的和就行了。
第三个操作就是查询版本 \(t\) 的区间维护的和。
第四个操作就直接把当前的版本变成目标版本就行了。
Code
#include <bits/stdc++.h>
using namespace std;
const long long N = 1e5 + 15;
int n, m, vis;
long long a[N];
int rt[N], idx;
struct tree {
int l, r;
long long v;
long long f;
}tr[N << 6];
inline void read (long long &x) {
x = 0;
int f = 1;
char ch = getchar ();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar ();}
while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + (ch ^ '0'); ch = getchar ();}
x *= f;
}
inline int build (int l, int r) {
int q = idx ++;
if (l == r) {
tr[q].v = a[l];
return q;
}
int mid = l + r >> 1;
tr[q].l = build (l, mid);
tr[q].r = build (mid + 1, r);
tr[q].v = tr[tr[q].l].v + tr[tr[q].r].v;
return q;
}
inline int update (int p, int l, int r, int x, int y, long long v) {
int q = idx ++;
tr[q] = tr[p];
if (l >= x && r <= y) {
tr[q].f += v;
tr[q].v += v * 1ll * (r - l + 1);
return q;
}
int mid = l + r >> 1;
if (x <= mid) tr[q].l = update (tr[p].l, l, mid, x, y, v);
if (y > mid) tr[q].r = update (tr[q].r, mid + 1, r, x, y, v);
tr[q].v = tr[tr[q].l].v + tr[tr[q].r].v + tr[q].f * (r - l + 1);
return q;
}
inline long long query (int q, int l, int r, int x, int y, long long v) {
if (l >= x && r <= y) {
return tr[q].v + v * 1ll * (r - l + 1);
}
int mid = l + r >> 1;
long long ans = 0ll;
if (x <= mid) ans += query (tr[q].l, l, mid, x, y, v + tr[q].f);
if (y > mid) ans += query (tr[q].r, mid + 1, r, x, y, v + tr[q].f);
return ans;
}
signed main () {
while (scanf ("%d%d", &n, &m) != EOF) {
idx = vis = 0;
for (int i = 1; i <= n; ++ i) {
read (a[i]);
}
rt[0] = build (1, n);
while (m --) {
char op[2];
long long l, r, t;
scanf ("%s", op);
read (l);
if (*op == 'C') {
read (r), read (t);
++ vis;
rt[vis] = update (rt[vis - 1], 1, n, l, r, t);
} else if (*op == 'Q') {
read (r);
printf ("%lld\n", query (rt[vis], 1, n, l, r, 0ll));
} else if (*op == 'H') {
read (r), read (t);
printf ("%lld\n", query (rt[t], 1, n, l, r, 0ll));
} else {
vis = l;
}
}
}
return 0;
}

浙公网安备 33010602011771号