首页 > 代码库 > [XSY 1019] 小A学树论 Splay维护入栈出栈序

[XSY 1019] 小A学树论 Splay维护入栈出栈序

题意

  给定一棵 n 个节点的树. 这棵树以 1 为根, 每个点有点权.

  在树上支持三种操作:

    ① 查询以 x 为根的子树的点权之和;

    ② 将以 x 为根的子树中的每个点的点权增加 w ;

    ③ 将 以 x 为根的子树转移到 y 的直接后继.

  $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 namespace Input {
 10     const int S = 2000000;
 11     char s[S], *h = s+S, *t = h;
 12     inline char getchr(void) { if (h == t) fread(s, 1, S, stdin), h = s; return *h++; }
 13     inline LL rd(void) {
 14         LL f = 1; char c = getchr(); for (; !isdigit(c); c = getchr()) if (c == -) f = -1;
 15         LL x = 0; for (; isdigit(c); c = getchr()) x = x*10+c-0; return x*f;
 16     }
 17 }
 18 using Input::rd;
 19  
 20 const int N = 200005;
 21  
 22 int n, m; LL w[N];
 23 vector<int> g[N];
 24 inline void Init(int x, int y) { g[x].push_back(y), g[y].push_back(x); }
 25  
 26 int tot, In[N], Out[N], List[N];
 27 inline void Add(int x, int sign) { List[++tot] = x, (sign == +1 ? In[x] = tot : Out[x] = tot); }
 28 inline void Prework(int x, int fa) {
 29     Add(x, +1);
 30     for (vector<int>::iterator it = g[x].begin(); it != g[x].end(); it++)
 31         if (*it != fa) Prework(*it, x);
 32     Add(x, -1);
 33 }
 34  
 35 #define LC (c[x][0])
 36 #define RC (c[x][1])
 37  
 38 int rt, c[N][2], par[N], siz[N];
 39 LL key[N], sum[N], tag[N];
 40  
 41 inline void Trav(int x) { if (!x) return; Trav(LC), printf("%d ", List[x]), Trav(RC); }
 42 void Put(int x) { Trav(x), puts(""); }
 43  
 44 inline void Up(int x) { siz[x] = siz[LC] + siz[RC] + 1, sum[x] = sum[LC] + sum[RC] + key[x]; }
 45 inline void Down(int x, LL tmp) { key[x] += tmp, sum[x] += siz[x] * tmp, tag[x] += tmp; }
 46 inline void Clear(int x) { if (!tag[x]) return; Down(LC, tag[x]), Down(RC, tag[x]), tag[x] = 0; }
 47  
 48 inline void Rot(int x) {
 49     int t = par[x], L = (c[t][1] == x), R = L^1;
 50      
 51     if (par[t] > 0)
 52         c[par[t]][c[par[t]][1] == t] = x;
 53     par[x] = par[t];
 54      
 55     if (c[x][R] > 0)
 56         par[c[x][R]] = t;
 57     c[t][L] = c[x][R];
 58      
 59     c[x][R] = t, par[t] = x;
 60     Up(t), Up(x);
 61 }
 62 inline void Splay(int x, int f = 0){
 63     static int L[N]; int tot = 0;
 64     L[++tot] = x;
 65     for (int i = x; par[i] != f; i = par[i]) L[++tot] = par[i];
 66     for (; tot > 0; L[tot--] = 0)
 67         Clear(L[tot]);
 68      
 69     for (; par[x] != f; Rot(x)) {
 70         int y = par[x], z = par[y];
 71         if (z != f && par[z] != f)
 72             (c[z][0] == y) ^ (c[y][0] == x) ? Rot(x) : Rot(y);
 73     }
 74     if (!f) rt = x;
 75 }
 76  
 77 void Build(int &x, int L, int R) {
 78     x = (L+R)>>1;
 79     key[x] = w[List[x]], siz[x] = 1;
 80     if (L < x) Build(LC, L, x-1), par[LC] = x;
 81     if (x < R) Build(RC, x+1, R), par[RC] = x;
 82     Up(x);
 83 }
 84  
 85 inline int Pre(int x) {
 86     Splay(x);
 87     int y = LC;
 88     while (c[y][1] > 0) y = c[y][1];
 89     Splay(y);
 90     return y;
 91 }
 92 inline int Nxt(int x) {
 93     Splay(x);
 94     int y = RC;
 95     while (c[y][0] > 0) y = c[y][0];
 96     Splay(y);
 97     return y;
 98 }
 99  
100 inline LL Sum(int x) {
101     int L = Pre(In[x]);
102     int R = Nxt(Out[x]);
103     Splay(L);
104     Splay(R, rt);
105     return sum[c[R][0]] >> 1;
106 }
107 inline void Addsub(int x, LL y) {
108     int L = Pre(In[x]);
109     int R = Nxt(Out[x]);
110     Splay(L);
111     Splay(R, rt);
112     Down(c[R][0], y);
113     Up(R), Up(rt);
114 }
115 inline void Linkcut(int x, int y) {
116     int L = Pre(In[x]);
117     int R = Nxt(Out[x]);
118     Splay(L);
119     Splay(R, rt);
120      
121     int now = c[R][0];
122     par[now] = c[R][0] = 0, Up(R), Up(L);
123      
124     L = In[y], R = Nxt(In[y]);
125     Splay(L);
126     Splay(R, rt);
127      
128     c[R][0] = now, par[now] = R, Up(R), Up(L);
129 }
130  
131 int main(void) {
132     #ifndef ONLINE_JUDGE
133         freopen("xsy1019.in", "r", stdin);
134         //  freopen("xsy1019.out", "w", stdout);
135     #endif
136      
137     n = rd(), m = rd();
138     F(i, 1, n) w[i] = rd();
139     F(i, 1, n-1) {
140         int x = rd(), y = rd();
141         Init(x, y);
142     }
143      
144     Add(0, +1);
145     Prework(1, -1);
146     Add(0, -1);
147      
148     tot = 0;
149     Build(rt, 1, 2*n+2);
150      
151     F(i, 1, m) {
152         int k = rd();
153         if (k == 1) {
154             int x = rd();
155             printf("%lld\n", Sum(x));
156         }
157         else if (k == 2) {
158             int x = rd(); LL y = rd();
159             Addsub(x, y);
160         }
161         else {
162             int x = rd(), y = rd();
163             Linkcut(x, y);
164         }
165     }
166      
167     return 0;
168 }

 

[XSY 1019] 小A学树论 Splay维护入栈出栈序