题意
给定一棵 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 }
时间: 2024-10-09 18:46:26