【题目链接】
第一次见到用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