Luogu 4556 雨天的尾巴

Solution

用$col$记录 数量最多的种类, $sum$记录 种类$col$ 的数量。

然后问题就是树上链修改, 求 每个节点 数量最多的种类。

用树上差分 + 线段树合并更新即可。

Code

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define rd read()
  5 using namespace std;
  6 
  7 const int N = 1e5 + 5;
  8 
  9 int head[N], cnt;
 10 int n, m;
 11 int sum[N], top[N], son[N], sz[N], f[N], dep[N];
 12 int u[N], v[N], z[N], b[N], tot, ans[N], idf[N];
 13 
 14 struct edge {
 15     int nxt, to;
 16 }e[N << 1];
 17 
 18 int read() {
 19     int X = 0, p = 1; char c = getchar();
 20     for (; c > '9' || c < '0'; c = getchar()) 
 21         if (c == '-') p = -1;
 22     for (; c >= '0' && c <= '9'; c = getchar())
 23         X = X * 10 + c - '0';
 24     return X * p;
 25 }
 26 
 27 void add(int u, int v) {
 28     e[++cnt].to = v;
 29     e[cnt].nxt = head[u];
 30     head[u] = cnt;
 31 }
 32 
 33 int fd(int x) {
 34     return lower_bound(b + 1, b + 1 + tot, x) - b;
 35 }
 36 
 37 namespace SegT {
 38 
 39     struct node {
 40         int sum, col, lson, rson;
 41         node() {
 42             sum = col = lson = rson = 0;
 43         }
 44     } s[N * 50];
 45 
 46     int root[N];
 47 
 48 #define lc(p) s[p].lson
 49 #define rc(p) s[p].rson
 50 #define sum(p) s[p].sum
 51 #define col(p) s[p].col
 52 #define mid ((l + r) >> 1)
 53 
 54     int st[N * 50], tp, qnum;
 55 
 56     int get() {
 57         if (tp) {
 58             int re = st[tp];
 59             tp--;
 60             return re;
 61         }
 62             
 63         else return ++qnum;
 64     }
 65 
 66     void del(int x) {
 67         lc(x) = rc(x) = sum(x) =  col(x) = 0;
 68         st[++tp] = x;
 69     }
 70 
 71     void up(int p) {
 72         if(sum(lc(p)) >= sum(rc(p)))
 73             sum(p) = sum(lc(p)), col(p) = col(lc(p));
 74         else 
 75             sum(p) = sum(rc(p)), col(p) = col(rc(p));
 76     }
 77 
 78     void modify(int l, int r, int pos, int d, int &x) {
 79         if(!x) x = get();
 80         if (l == r) {
 81             sum(x) += d;
 82             if (sum(x) > 0) 
 83                 col(x) = pos;
 84             return;
 85         }
 86         if (pos <= mid)
 87             modify(l, mid, pos, d, lc(x));
 88         else 
 89             modify(mid + 1, r, pos, d, rc(x));
 90         up(x);
 91     }
 92 
 93     int merge(int l, int r, int x, int y) {
 94         if (!x || !y)
 95             return x + y;
 96         int now = get();
 97         if (l == r) {
 98             sum(now) = sum(x) + sum(y);
 99             if (sum(now) > 0)
100                 col(now) = max(col(x), col(y));
101             else col(now) = 0;
102         }
103         else {
104             lc(now) = merge(l, mid, lc(x), lc(y));
105             rc(now) = merge(mid + 1, r, rc(x), rc(y));
106             up(now);
107         }
108         del(x); del(y);
109         return now;
110     }
111 }
112 
113 using namespace SegT;
114 
115 namespace SP {
116     void dfs1(int x) {
117         sz[x] = 1;
118         for (int i = head[x]; i; i = e[i].nxt) {
119             int nt = e[i].to;
120             if (nt == f[x])
121                 continue;
122             f[nt] = x;
123             dep[nt] = dep[x] + 1;
124             SP::dfs1(nt);
125             sz[x] += sz[nt];
126             if (sz[nt] > sz[son[x]])
127                 son[x] = nt;
128         }
129     }
130 
131     void dfs2(int x) {
132         if (!son[x])
133             return;
134         top[son[x]] = top[x];
135         SP::dfs2(son[x]);
136         for (int i = head[x]; i; i = e[i].nxt) {
137             int nt = e[i].to;
138             if (nt == f[x] || nt == son[x])
139                 continue;
140             top[nt] = nt;
141             SP::dfs2(nt);
142         }
143     }
144 
145     int LCA(int x, int y) {
146         for (; top[x] != top[y];) {
147             if (dep[top[x]] < dep[top[y]])
148                 swap(x, y);
149             x = f[top[x]];
150         }
151         if (dep[x] < dep[y])
152             swap(x, y);
153         return y;
154     }
155 
156     void solve(int x) {
157         for (int i = head[x]; i; i = e[i].nxt) {
158             int nt = e[i].to;
159             if (nt == f[x])
160                 continue;
161             SP::solve(nt);
162             root[x] = merge(1, tot, root[x], root[nt]);
163         }
164         ans[x] = col(root[x]);
165     }
166 }
167 
168 int main()
169 {
170     n = rd; m = rd;
171     for (int i = 1; i < n; ++i) {
172         int x = rd, y = rd;
173         add(x, y); add(y, x);
174     }
175     dep[1] = 1;
176     SP::dfs1(1);
177     top[1] = 1;
178     SP::dfs2(1);
179     for (int i = 1; i <= m; ++i) {
180         u[i] = rd; v[i] = rd;
181         z[i] = b[i] = rd;
182     }
183     tot = m;
184     sort(b + 1, b + 1 + tot);
185     tot = unique(b + 1, b + 1 + tot) - b - 1;
186     for (int i = 1; i <= tot; ++i)
187         idf[b[i]] = i;
188     for (int i = 1; i <= m; ++i) {
189         int lca = SP::LCA(u[i], v[i]);
190         modify(1, tot, idf[z[i]], 1, root[u[i]]);
191         modify(1, tot, idf[z[i]], 1, root[v[i]]);
192         modify(1, tot, idf[z[i]], -1, root[lca]);
193         modify(1, tot, idf[z[i]], -1, root[f[lca]]);
194     }
195     SP::solve(1);
196     for (int i = 1; i <= n; ++i)
197         printf("%d
" ,b[ans[i]]);
198 }
View Code
原文地址:https://www.cnblogs.com/cychester/p/9679854.html