【国家集训队】Tree II

Description

给定n个点的树,每个点有点权,维护如下操作:

  • 将某一条链上的点的点权加或者乘一个数
  • 将原有的一条边删除,加入一条新边,并保证操作完之后是一棵树
  • 询问某一条链上所有点权之和

Solution

LCT维护

每一个点维护如下信息:父亲,儿子,点权,子树大小,子树的点权和,翻转标记,乘法标记,加法标记

这是一道LCT的模板题,难点在于处理三个标记的下放问题

根据运算优先级,乘法是要先算的,所以先放,放的时候子树的sum,乘法标记,加法标记,儿子的val统统都要乘一遍
放加法标记的时候,想到线段树的区间大小是稳定的,而Splay并不是,所以还要维护size,于是子树的sum要加上子树的size再乘上标记,而儿子的val和加法标记直接加上该标记的值
再注意一个小细节即可

Code

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef unsigned int ll;
  4 const int mod = 51061;
  5 const int N = 1e5 + 10;
  6 inline int read() {
  7     int ret = 0, op = 1;
  8     char c = getchar();
  9     while (!isdigit(c)) {
 10         if (c == '-') op = -1; 
 11         c = getchar();
 12     }
 13     while (isdigit(c)) {
 14         ret = ret * 10 + c - '0';
 15         c = getchar();
 16     }
 17     return ret * op;
 18 }
 19 struct LCT {
 20     int fa, ch[2], size;
 21     ll val;
 22     ll sum;
 23     ll atag, mtag, tag;
 24 } a[N];
 25 int n, m, s[N];
 26 inline void update(int now) {
 27     a[now].size = a[a[now].ch[0]].size + a[a[now].ch[1]].size + 1;
 28     a[now].sum = (a[a[now].ch[0]].sum + a[a[now].ch[1]].sum + a[now].val) % mod;
 29 }
 30 void add(ll &x, int y) {
 31     x += y;
 32     x %= mod;
 33 }    
 34 void mul(ll &x, int y) {
 35     x *= y;
 36     x %= mod;
 37 }
 38 void rev(int now) {
 39     swap(a[now].ch[0], a[now].ch[1]);
 40     a[now].tag ^= 1;
 41 }
 42 void pushdown(int now) {
 43     if (a[now].mtag != 1) {
 44         mul(a[a[now].ch[0]].sum, a[now].mtag); mul(a[a[now].ch[0]].val, a[now].mtag); mul(a[a[now].ch[0]].mtag, a[now].mtag); mul(a[a[now].ch[0]].atag, a[now].mtag);
 45         mul(a[a[now].ch[1]].sum, a[now].mtag); mul(a[a[now].ch[1]].val, a[now].mtag); mul(a[a[now].ch[1]].mtag, a[now].mtag); mul(a[a[now].ch[1]].atag, a[now].mtag);
 46         a[now].mtag = 1;
 47     }
 48     if (a[now].atag) {
 49         add(a[a[now].ch[0]].sum, a[now].atag * a[a[now].ch[0]].size);
 50         add(a[a[now].ch[0]].val, a[now].atag);
 51         add(a[a[now].ch[0]].atag, a[now].atag);
 52         add(a[a[now].ch[1]].sum, a[now].atag * a[a[now].ch[1]].size);
 53         add(a[a[now].ch[1]].val, a[now].atag);
 54         add(a[a[now].ch[1]].atag, a[now].atag);        
 55         a[now].atag = 0;
 56     }
 57     if (a[now].tag) {
 58         if (a[now].ch[0]) rev(a[now].ch[0]);
 59         if (a[now].ch[1]) rev(a[now].ch[1]);
 60         a[now].tag = 0;    
 61     }
 62 }
 63 inline int isnroot(int now) {
 64     return a[a[now].fa].ch[0] == now || a[a[now].fa].ch[1] == now;
 65 }
 66 inline void rotate(int x) {
 67     int y = a[x].fa;
 68     int z = a[y].fa;
 69     int xson = a[y].ch[1] == x;
 70     int yson = a[z].ch[1] == y;
 71     int B = a[x].ch[xson ^ 1];
 72     if (isnroot(y)) a[z].ch[yson] = x; a[x].ch[xson ^ 1] = y; a[y].ch[xson] = B;
 73     if (B) a[B].fa = y; a[y].fa = x; a[x].fa = z;
 74     update(y);
 75 }
 76 inline void splay(int x) {
 77     int y = x, z = 0;
 78     s[++z] = y;
 79     while (isnroot(y)) y = a[y].fa, s[++z] = y;
 80     while (z) pushdown(s[z--]);
 81     while (isnroot(x)) {
 82         y = a[x].fa;
 83         z = a[y].fa;
 84         if (isnroot(y)) 
 85             (a[z].ch[1] == y) ^ (a[y].ch[1] == x) ? rotate(x) : rotate(y);
 86         rotate(x);
 87     }
 88     update(x);
 89 }
 90 void access(int x) {
 91     for (register int y = 0; x; y = x, x = a[x].fa) {
 92         splay(x); a[x].ch[1] = y; update(x);
 93     }
 94 }
 95 void makeroot(int x) {
 96     access(x);
 97     splay(x);
 98     rev(x);
 99 }
100 void split(int x, int y) {
101     makeroot(x);
102     access(y);
103     splay(y);
104 }
105 void link(int x, int y) {
106     makeroot(x);
107     a[x].fa = y;
108 }
109 void cut(int x, int y) {
110     split(x, y);
111     a[x].fa = a[y].ch[0] = 0;
112 }
113 int main() {
114     n = read(); m = read();
115     for (register int i = 1; i <= n; ++i) {
116         a[i].val = a[i].size = a[i].mtag = 1;
117     }
118     for (register int i = 1; i < n; ++i) {
119         int x = read(), y = read();
120         link(x, y);
121     }
122     while (m--) {
123         char op = getchar();
124         int x0, x1, x2;
125         if (op == '+') {
126             x0 = read(), x1 = read(), x2 = read();
127             split(x0, x1);
128             add(a[x1].sum, x2 * a[x1].size);
129             add(a[x1].val, x2);
130             add(a[x1].atag, x2);
131         }
132         else if (op == '-') {
133             x0 = read(), x1 = read(); cut(x0, x1);
134             x0 = read(), x1 = read(); link(x0, x1);
135         }
136         else if (op == '*') {
137             x0 = read(), x1 = read(), x2 = read();
138             split(x0, x1);
139             mul(a[x1].sum, x2);
140             mul(a[x1].val, x2);
141             mul(a[x1].mtag, x2);
142             mul(a[x1].atag, x2);
143         }
144         else {
145             x0 = read(), x1 = read();
146             split(x0, x1);
147             printf("%d
", a[x1].sum);
148         }
149     }
150     return 0;
151 }
AC Code
原文地址:https://www.cnblogs.com/shl-blog/p/11350682.html