[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维护入栈出栈序的主要内容,如果未能解决你的问题,请参考以下文章

Bzoj3786: 星系探索——Splay

bzoj3786星系探索

bzoj3786星系探索 splay

BZOJ-3786星系探索 Splay + DFS序

bzoj 3786 星系探索 dfs+splay

BZOJ3786星系探索 DFS序+Splay