第一次见到用Splay维护DFS序的题。
(其实一开始看jiry_2题解,写的LCT,结果TLE / RE。重新思考人生后换成了Splay)
又忘把标记下传了。。
/* Pigonometry */
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 200005, maxm = 100005, maxnode = 400005;
int n, m, head[maxn], cnt, q[maxn], tot, val[maxn];
struct _edge {
int v, next;
} g[maxm << 1];
template <class numtype>
inline void read(numtype &x) {
bool f = 0; x = 0; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) f = (ch == '-');
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
if(f) x = -x;
}
inline void add(int u, int v) {
g[cnt] = (_edge){v, head[u]};
head[u] = cnt++;
}
inline void dfs(int x, int f) {
q[++tot] = (x << 1) - 1;
for(int i = head[x]; ~i; i = g[i].next) if(g[i].v ^ f)
dfs(g[i].v, x);
q[++tot] = x << 1;
}
/* Splay */
int son[maxnode][2], size[maxnode], pre[maxnode], root, w[maxnode], addv[maxnode];
LL sum[maxnode];
inline void pushup(int x) {
int l = son[x][0], r = son[x][1];
size[x] = size[l] + 1 + size[r];
sum[x] = sum[l] + w[x] + sum[r];
}
inline void pushdown(int x) {
int l = son[x][0], r = son[x][1];
if(addv[x]) {
if(l) {
w[l] += addv[x];
sum[l] += (LL)size[l] * addv[x];
addv[l] += addv[x];
}
if(r) {
w[r] += addv[x];
sum[r] += (LL)size[r] * addv[x];
addv[r] += addv[x];
}
addv[x] = 0;
}
}
inline void newnode(int &x, int f, int c) {
x = ++tot;
pre[x] = f;
w[x] = sum[x] = c;
addv[x] = 0;
}
inline int build(int l, int r, int f) {
if(l > r) return 0;
int mid = l + r >> 1, x = q[mid];
pre[x] = f;
w[x] = sum[x] = val[(x + 1) >> 1];
addv[x] = 0;
son[x][0] = build(l, mid - 1, x); son[x][1] = build(mid + 1, r, x);
pushup(x);
return x;
}
inline void init() {
root = 0;
son[0][0] = son[0][1] = size[0] = pre[0] = sum[0] = 0;
root = build(1, tot, root);
pushup(root);
}
inline void rotate(int x) {
int y = pre[x], z = pre[y], type = son[y][1] == x;
pushdown(y); pushdown(x);
pre[son[y][type] = son[x][!type]] = y;
pre[x] = z;
if(z) son[z][son[z][1] == y] = x;
pre[son[x][!type] = y] = x;
pushup(y); pushup(x);
}
inline void splay(int x, int goal) {
while(pre[x] ^ goal) {
int y = pre[x], z = pre[y];
if(z == goal) rotate(x);
else if(son[z][1] == y ^ son[y][1] == x) rotate(x), rotate(x);
else rotate(y), rotate(x);
}
if(!goal) root = x;
}
inline int getpre(int x) {
for(x = son[x][0]; son[x][1]; x = son[x][1]);
return x;
}
inline int getsuf(int x) {
for(x = son[x][1]; son[x][0]; x = son[x][0]);
return x;
}
inline void insert(int x, int c) {
x = (x << 1) - 1; splay(x, 0);
int y = getsuf(x); splay(y, x);
newnode(son[y][0], y, c);
newnode(son[son[y][0]][1], son[y][0], c);
pushup(son[son[y][0]][1]); pushup(son[y][0]);
pushup(y); pushup(x);
}
inline void addw(int x, int c) {
x = (x << 1) - 1;
splay(x, 0); splay(x + 1, x);
int y = son[x + 1][0];
if(y) {
w[y] += c;
addv[y] += c;
sum[y] += (LL)size[y] * c;
}
w[x] += c; w[x + 1] += c;
pushup(x + 1); pushup(x);
}
inline void del(int x) {
x = (x << 1) - 1;
splay(x, 0); splay(x + 1, x);
int l = getpre(x), r = getsuf(x + 1);
splay(l, 0); splay(r, l);
pre[son[r][0]] = 0; son[r][0] = 0;
pushup(r); pushup(l);
}
inline LL query(int x) {
x = (x << 1) - 1;
splay(x, 0); splay(x + 1, x);
return (sum[son[x + 1][0]] >> 1) + w[x];
}
int main() {
read(n);
for(int i = 1; i <= n; i++) read(val[i]), head[i] = -1; cnt = tot = 0;
for(int i = 1; i < n; i++) {
int u, v; read(u); read(v); u++; v++;
add(u, v); add(v, u);
}
dfs(1, 0);
init();
LL ans = 0;
read(m);
while(m--) {
int opt; read(opt);
LL x; read(x); x += ans + 1;
if(opt == 1) {
int v; read(v);
insert(x, v);
}
else if(opt == 2) {
int v; read(v);
addw(x, v);
}
else if(opt == 3)
del(x);
else if(opt == 4)
printf("%lld\n", ans = query(x));
}
return 0;
}
附比样例强一点的数据
2
10 20
0 1
9
4 0
1 -30 5
2 -30 1
4 -30
3 -37
4 -38
1 -15 233
4 -17
4 -248