CSU1811: Tree Intersection

Posted ichneumon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSU1811: Tree Intersection相关的知识,希望对你有一定的参考价值。

题目大意

给一棵点带颜色的树,问依次删掉每条边后得到的两棵子树出现的颜色并集的大小。

简要题解

注意这么一个性质,一种颜色在两棵树中出现,则在一棵树中出现,且出现次数小于总的出现次数。

然后需要这么一个数据结构,能维护子树内出现的颜色和对应的出现次数。

用数组启发式合并或者线段树合并即可。

之前写了一发,拍了好久没问题,交上去就RE,好气。

今天重新写了一发,写完直接AC,神清气爽hhh

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 namespace my_header {
  4 #define pb push_back
  5 #define mp make_pair
  6 #define pir pair<int, int>
  7 #define vec vector<int>
  8 #define pc putchar
  9 #define clr(t) memset(t, 0, sizeof t)
 10 #define pse(t, v) memset(t, v, sizeof t)
 11 #define bl puts("")
 12 #define wn(x) wr(x), bl
 13 #define ws(x) wr(x), pc(‘ ‘)
 14     const int INF = 0x3f3f3f3f;
 15     typedef long long LL;
 16     typedef double DB;
 17     inline char gchar() {
 18         char ret = getchar();
 19         for(; (ret == \n || ret == \r || ret ==  ) && ret != EOF; ret = getchar());
 20         return ret; }
 21     template<class T> inline void fr(T &ret, char c =  , int flg = 1) {
 22         for(c = getchar(); (c < 0 || 9 < c) && c != -; c = getchar());
 23         if (c == -) { flg = -1; c = getchar(); }
 24         for(ret = 0; 0 <= c && c <= 9; c = getchar())
 25             ret = ret * 10 + c - 0;
 26         ret = ret * flg; }
 27     inline int fr() { int t; fr(t); return t; }
 28     template<class T> inline void fr(T&a, T&b) { fr(a), fr(b); }
 29     template<class T> inline void fr(T&a, T&b, T&c) { fr(a), fr(b), fr(c); }
 30     template<class T> inline char wr(T a, int b = 10, bool p = 1) {
 31         return a < 0 ? pc(-), wr(-a, b, 0) : (a == 0 ? (p ? pc(0) : p) : 
 32             (wr(a/b, b, 0), pc(0 + a % b)));
 33     }
 34     template<class T> inline void wt(T a) { wn(a); }
 35     template<class T> inline void wt(T a, T b) { ws(a), wn(b); }
 36     template<class T> inline void wt(T a, T b, T c) { ws(a), ws(b), wn(c); }
 37     template<class T> inline void wt(T a, T b, T c, T d) { ws(a), ws(b), ws(c), wn(d); }
 38     template<class T> inline T gcd(T a, T b) {
 39         return b == 0 ? a : gcd(b, a % b); }
 40     template<class T> inline T fpw(T b, T i, T _m, T r = 1) {
 41         for(; i; i >>= 1, b = b * b % _m)
 42             if(i & 1) r = r * b % _m;
 43         return r; }
 44 };
 45 using namespace my_header;
 46 
 47 const int MAXN = 5e6 + 100;
 48 const int MAXV = 2e5 + 100;
 49 int n, col[MAXV], fa[MAXV], cnt[MAXV], ans[MAXV];
 50 int h[MAXV], nxt[MAXV], to[MAXV], e;
 51 
 52 #define lc ch[0]
 53 #define rc ch[1]
 54 struct SegNode {
 55     SegNode *ch[2];
 56     int s, c;
 57     void init() {
 58         s = c = 0;
 59         lc = rc = NULL;
 60     }
 61     void update();
 62     void merge(int, int, SegNode*);
 63     void insert(int, int, int);
 64 } node_pool[MAXN], *loc, *root[MAXV];
 65 SegNode* newSegNode() {
 66     loc->init();
 67     return loc++;
 68 }
 69 
 70 void SegNode::update() {
 71     s = (lc ? lc->s : 0) + (rc ? rc->s : 0);
 72 }
 73 void SegNode::insert(int l, int r, int v) {
 74     if (l == r) {
 75         ++c;
 76         s = (c != cnt[l]);
 77     } else {
 78         int m = (l + r) >> 1;
 79         if (v <= m) {
 80             if (!lc)
 81                 lc = newSegNode();
 82             lc->insert(l, m, v);
 83         } else {
 84             if (!rc)
 85                 rc = newSegNode();
 86             rc->insert(m + 1, r, v);
 87         }
 88         update();
 89     }
 90 }
 91 void SegNode::merge(int l, int r, SegNode* v) {
 92     if (l == r) {
 93         if (v) {
 94             c += v->c;
 95             s = (c != cnt[l]);
 96         }
 97     } else {
 98         int m = (l + r) >> 1;
 99         if (!lc)
100             lc = v->lc;
101         else if (v->lc)
102             lc->merge(l, m, v->lc);
103         if (!rc)
104             rc = v->rc;
105         else if (v->rc)
106             rc->merge(m + 1, r, v->rc);
107         update();
108     }
109 }
110 
111 void dfs(int u) {
112     int w = -1;
113     root[u] = newSegNode();
114     root[u]->insert(1, n, col[u]);
115     for (int i = h[u]; i != -1; i = nxt[i]) {
116         int v = to[i];
117         if (v != fa[u]) {
118             fa[v] = u;
119             dfs(v);
120             root[u]->merge(1, n, root[v]);
121         } else w = i >> 1;
122     }
123     if (w != -1)
124         ans[w] = root[u]->s;
125 }
126 
127 int main() {
128 #ifdef lol
129     freopen("1811.in", "r", stdin);
130     freopen("1811.out", "w", stdout);
131 #endif
132 
133     while (scanf("%d", &n) != EOF) {
134         for (int i = 1; i <= n; ++i)
135             cnt[i] = 0;
136         for (int i = 1; i <= n; ++i) {
137             fr(col[i]);
138             ++cnt[col[i]];
139         }
140         e = 0;
141         memset(h, -1, sizeof h);
142         for (int i = 1; i < n; ++i) {
143             int u, v;
144             fr(u, v);
145             to[e] = v, nxt[e] = h[u], h[u] = e++;
146             to[e] = u, nxt[e] = h[v], h[v] = e++;
147         }
148         loc = node_pool;
149         dfs(1);
150         for (int i = 0; i < n - 1; ++i)
151             wt(ans[i]);
152     }
153 
154     return 0;
155 }

 

以上是关于CSU1811: Tree Intersection的主要内容,如果未能解决你的问题,请参考以下文章

CSU1811: Tree Intersection

CSU 1811 Tree Intersection(平衡树的子树合并)

CSU 1663: Tree(树链剖分)

CSU 1974: 神奇药水

CSU-2116 Polyline Simplification

CSU-2034 Column Addition