[BZOJ 3786] 星系探索 Splay维护入栈出栈序
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ 3786] 星系探索 Splay维护入栈出栈序相关的知识,希望对你有一定的参考价值。
题意
给定一棵 n 个节点, 点有点权, 以 1 为根的有根树.
m 次操作:
① 查询点 d 到根的点权之和.
② 将 x 及其子树截出来, 作为 y 的儿子.
③ 将以 p 为根的子树的点权增加 q .
$n \le 100000$ .
实现
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #include <vector> 6 using namespace std; 7 #define F(i, a, b) for (register int i = (a); i <= (b); i++) 8 #define LL long long 9 inline int rd(void) { 10 int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; 11 int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; 12 } 13 inline char rdc(void) { char c = getchar(); for (; !isalpha(c); c = getchar()); return c; } 14 15 const int N = 200005; 16 17 #define fore(it, x) for (register vector<int>::iterator it = g[x].begin(); it != g[x].end(); it++) 18 int n, w[N]; 19 vector<int> g[N]; 20 21 int tot, List[N], In[N], Out[N]; 22 void Prework(int x) { 23 List[++tot] = x, In[x] = tot; 24 fore(it, x) 25 Prework(*it); 26 List[++tot] = x, Out[x] = tot; 27 } 28 29 #define LC (c[x][0]) 30 #define RC (c[x][1]) 31 32 int rt, c[N][2], par[N]; 33 LL key[N], sign[N], cnt[N], sum[N], tag[N]; 34 35 inline void Pushup(int x) { cnt[x] = cnt[LC] + cnt[RC] + sign[x], sum[x] = sum[LC] + sum[RC] + key[x] * sign[x]; } 36 inline void Push(int x, LL t) { key[x] += t, sum[x] += cnt[x] * t, tag[x] += t; } 37 inline void Clear(int x) { 38 if (!tag[x]) return; 39 if (LC > 0) Push(LC, tag[x]); 40 if (RC > 0) Push(RC, tag[x]); 41 tag[x] = 0; 42 } 43 44 inline void Rot(int x) { 45 int t = par[x]; 46 int L = (c[t][1] == x), R = L^1; 47 48 if (par[t] > 0) 49 c[par[t]][c[par[t]][1] == t] = x; 50 par[x] = par[t]; 51 52 if (c[x][R] > 0) 53 par[c[x][R]] = t; 54 c[t][L] = c[x][R]; 55 56 c[x][R] = t, par[t] = x; 57 Pushup(t), Pushup(x); 58 } 59 inline void Splay(int x, int f = 0) { 60 static int L[N]; int tot = 0; 61 L[++tot] = x; 62 for (int i = x; par[i] != f; i = par[i]) L[++tot] = par[i]; 63 for (; tot > 0; L[tot--] = 0) 64 Clear(L[tot]); 65 66 for (; par[x] != f; Rot(x)) { 67 int y = par[x], z = par[y]; 68 if (z != f && par[z] != f) (c[z][0] == y) ^ (c[y][0] == x) ? Rot(x) : Rot(y); 69 } 70 if (!f) rt = x; 71 } 72 73 void Build(int &x, int L, int R) { 74 x = (L+R)>>1; 75 if (List[x] > 0) 76 sign[x] = (In[List[x]] == x ? 1 : -1), key[x] = w[List[x]]; 77 if (L < x) Build(LC, L, x-1), par[LC] = x; 78 if (x < R) Build(RC, x+1, R), par[RC] = x; 79 Pushup(x); 80 } 81 82 inline int Pre(int x) { 83 // Find Pre(x) and Splay it to Root ! 84 Splay(x); 85 int y = LC; while (c[y][1] > 0) y = c[y][1]; 86 Splay(y); 87 return y; 88 } 89 inline int Nxt(int x) { 90 Splay(x); 91 int y = RC; while (c[y][0] > 0) y = c[y][0]; 92 Splay(y); 93 return y; 94 } 95 96 inline LL Query(int di) { 97 int x = Nxt(In[di]); 98 Splay(x); 99 return sum[LC]; 100 } 101 inline void Depend(int xi, int yi) { 102 int L = Pre(In[xi]); 103 int R = Nxt(Out[xi]); 104 Splay(L); 105 Splay(R); 106 int x = c[rt][0], y = c[x][1]; 107 c[x][1] = par[y] = 0, Pushup(x), Pushup(rt); 108 109 L = In[yi], R = Nxt(In[yi]); 110 Splay(L); 111 Splay(R); 112 x = c[rt][0]; 113 c[x][1] = y, par[y] = x, Pushup(x), Pushup(rt); 114 } 115 inline void Inspire(int pi, int qi) { 116 int L = Pre(In[pi]); 117 int R = Nxt(Out[pi]); 118 Splay(L); 119 Splay(R); 120 int x = c[rt][0], y = c[x][1]; 121 Push(y, qi); 122 Pushup(x), Pushup(rt); 123 } 124 125 void Get(int x) { if (!x) return; Clear(x); Get(LC); printf("%lld ", key[x]); Get(RC); } 126 void Print(int x) { Get(x); puts(""); } 127 128 int main(void) { 129 #ifndef ONLINE_JUDGE 130 freopen("bzoj3786.in", "r", stdin); 131 // freopen("bzoj3786.out", "w", stdout); 132 #endif 133 134 n = rd(); 135 F(i, 2, n) g[rd()].push_back(i); 136 F(i, 1, n) w[i] = rd(); 137 138 List[++tot] = 0, In[0] = tot; 139 Prework(1); 140 List[++tot] = 0, Out[0] = tot; 141 142 Build(rt, 1, 2*n+2); 143 // [1, 2n+2] 144 145 int m = rd(); 146 F(nC, 1, m) { 147 char c = rdc(); 148 if (c == ‘Q‘) { 149 int di = rd(); 150 printf("%lld\n", Query(di)); 151 } 152 else if (c == ‘C‘) { 153 int xi = rd(), yi = rd(); 154 Depend(xi, yi); 155 } 156 else { 157 int pi = rd(), qi = rd(); 158 Inspire(pi, qi); 159 } 160 } 161 162 return 0; 163 }
以上是关于[BZOJ 3786] 星系探索 Splay维护入栈出栈序的主要内容,如果未能解决你的问题,请参考以下文章