Description


i, and the i-th edge connects vertices a i and b i.



Let C(x,y) denotes the set of colors in subtree rooted at vertex x deleting edge (x,y).



i,b i) and C(b i,a i) for all 1≤i≤(n-1). (i.e. |C(a i,b i)∩C(b i,a i)|)


Input


The input contains at most 15 sets. For each set:



5).



1,c 2,…,c n



i,b i (1≤a i,b i≤n).


Output


1,R 2,…,R n-1.


Sample Input

4
1 2 2 1
1 2
2 3
3 4
5
1 1 2 1 2
1 3
2 3
3 5
4 5

Sample Output

#include<set>
#include<map>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define rep(i,j,k) for (int i = j; i <= k; i++)
#define per(i,j,k) for (int i = j; i >= k; i--)
#define loop(i,j,k) for (int i = j;i != -1; i = k[i])
#define lson x << 1, l, mid
#define rson x << 1 | 1, mid + 1, r
#define ff first
#define ss second
#define mp(i,j) make_pair(i,j)
#define pb push_back
#define pii pair<int,LL>
#define in(x) scanf("%d", &x);
using namespace std;
typedef long long LL;
const int low(int x) { return x&-x; }
const double eps = 1e-9;
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
int n, col[N], x, y;
int ft[N], nt[N], u[N], v[N], sz;
int Ft[N], Nt[N], U[N], V[N], Sz;
int d[N], t, pre[N], L[N], R[N];
int f[N], ans[N];

void dfs(int x, int fa)
{
d[pre[x] = ++t] = x;
L[col[x]] = min(L[col[x]], t);
R[col[x]] = max(R[col[x]], t);
loop(i, ft[x], nt)
{
if (u[i] == fa) continue;
dfs(u[i], x);
U[Sz] = pre[u[i]]; V[Sz] = v[i];
Nt[Sz] = Ft[t]; Ft[t] = Sz++;
}
}

void add(int x, int y)
{
for (int i = x; i <= n; i += low(i)) f[i] += y;
}

int get(int x)
{
int res = 0;
for (int i = x; i; i -= low(i)) res += f[i];
return res;
}

int main()
{
while (scanf("%d", &n) != EOF)
{
Sz = sz = t = 0;
rep(i, 1, n) in(col[i]);
rep(i, 1, n) Ft[i] = ft[i] = -1;
rep(i, 1, n) L[i] = n + 1, R[i] = f[i] = 0;
rep(i, 1, n - 1)
{
in(x); in(y);
u[sz] = y; v[sz] = i; nt[sz] = ft[x]; ft[x] = sz++;
u[sz] = x; v[sz] = i; nt[sz] = ft[y]; ft[y] = sz++;
}
dfs(1, 0);
rep(i, 1, n) pre[i] = f[i] = 0;
rep(i, 1, n)
{
add(pre[col[d[i]]] + 1, 1); add(i + 1, -1); pre[col[d[i]]] = i;
if (i == R[col[d[i]]]) add(1, -1), add(L[col[d[i]]] + 1, 1);
loop(j, Ft[i], Nt) ans[V[j]] = get(U[j]);
}
rep(i, 1, n - 1) printf("%d\n", ans[i]);
}
return 0;
}

换一种角度思考,同样是树形态,如果我们可以统计出某个节点全部儿子的情况,那么将儿子的状态全部合并加上当前节点的颜色就可以得到答案。

然后问题是怎么快速的合并统计答案,这个时候可以用启发式合并,线段树和splay都可以轻松的完成这种操作。

#include<set>
#include<map>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define rep(i,j,k) for (int i = j; i <= k; i++)
#define per(i,j,k) for (int i = j; i >= k; i--)
#define loop(i,j,k) for (int i = j;i != -1; i = k[i])
#define lson x << 1, l, mid
#define rson x << 1 | 1, mid + 1, r
#define ff first
#define ss second
#define mp(i,j) make_pair(i,j)
#define pb push_back
#define pii pair<int,LL>
#define in(x) scanf("%d", &x);
using namespace std;
typedef long long LL;
const int low(int x) { return x&-x; }
const double eps = 1e-9;
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
const int M = 2e6 + 10;
int n, x, y, col[N], cnt[N], ans[N], t[N];
int ft[N], nt[N], u[N], v[N], sz;
int L[M], R[M], f[M], g[M], tot;

int node()
{
L[tot] = R[tot] = f[tot] = g[tot] = 0; return tot++;
}

void make(int &x, int l, int r, int u)
{
if (!x) x = node();
if (l == r) f[x] = g[x] = 1 % cnt[u];
else
{
int mid = l + r >> 1;
if (u <= mid) make(L[x], l, mid, u);
else make(R[x], mid + 1, r, u);
f[x] = f[L[x]] + f[R[x]];
}
}

void merge(int &x, int y, int l, int r)
{
if (!x || !y) { x = x^y; return; }
if (l == r) f[x] = (bool)(g[x] = (g[x] + g[y]) % cnt[l]);
else
{
int mid = l + r >> 1;
merge(L[x], L[y], l, mid);
merge(R[x], R[y], mid + 1, r);
f[x] = f[L[x]] + f[R[x]];
}
}

void dfs(int x, int fa)
{
make(t[x] = 0, 1, n, col[x]);
loop(i, ft[x], nt)
{
if (u[i] == fa) continue;
dfs(u[i], x);
ans[v[i]] = f[t[u[i]]];
merge(t[x], t[u[i]], 1, n);
}
}

int main()
{
while (scanf("%d", &n) != EOF)
{
tot = sz = 0; node();
rep(i, 1, n) cnt[i] = 0, ft[i] = -1;
rep(i, 1, n) { in(col[i]); cnt[col[i]]++; }
rep(i, 1, n - 1)
{
in(x); in(y);
u[sz] = y; v[sz] = i; nt[sz] = ft[x]; ft[x] = sz++;
u[sz] = x; v[sz] = i; nt[sz] = ft[y]; ft[y] = sz++;
}
dfs(1, 0);
rep(i, 1, n - 1) printf("%d\n", ans[i]);
}
return 0;
}



Splay版,好久没写回忆一下,神奇的是试了一下,单纯的平衡树速度反而快一点,加了splay时间却增加了。

#include<set>
#include<map>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define rep(i,j,k) for (int i = j; i <= k; i++)
#define per(i,j,k) for (int i = j; i >= k; i--)
#define loop(i,j,k) for (int i = j;i != -1; i = k[i])
#define lson x << 1, l, mid
#define rson x << 1 | 1, mid + 1, r
#define ff first
#define ss second
#define mp(i,j) make_pair(i,j)
#define pb push_back
#define pii pair<int,LL>
#define in(x) scanf("%d", &x);
using namespace std;
typedef long long LL;
const int low(int x) { return x&-x; }
const double eps = 1e-9;
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
const int M = 2e6 + 10;
int n, x, y, col[N], cnt[N], ans[N], t[N];
int ft[N], nt[N], u[N], v[N], sz;

struct Splays
{
int ch[M][2], F[M], sz;
int A[M], B[M], C[M];
int Node(int f, int c, int z)
{
F[sz] = f; A[sz] = c; C[sz] = (bool)(B[sz] = z % cnt[c]);
ch[sz][0] = ch[sz][1] = 0; return sz++;
}
void clear() { sz = 1; ch[0][0] = ch[0][1] = F[0] = 0; C[0] = 0; }
void rotate(int x, int k)
{
int y = F[x]; ch[y][!k] = ch[x][k]; F[ch[x][k]] = y;
if (F[y]) ch[F[y]][y == ch[F[y]][1]] = x;
F[x] = F[y]; F[y] = x; ch[x][k] = y;
C[x] = C[y]; C[y] = C[ch[y][0]] + C[ch[y][1]] + (bool)B[y];
}
void Splay(int x, int r)
{
while (F[x] != r)
{
if (F[F[x]] == r) { rotate(x, x == ch[F[x]][0]); return; }
int y = (x == ch[F[x]][0]), z = (F[x] == ch[F[F[x]]][0]);
y^z ? (rotate(x, y), rotate(x, z)) : (rotate(F[x], z), rotate(x, y));
}
}
void insert(int &x, int fa, int y, int z)
{
if (!x) { x = Node(fa, y, z); return; }
if (A[x] == y)
{
B[x] = (B[x] + z) % cnt[y];
C[x] = C[ch[x][0]] + C[ch[x][1]] + (bool)B[x];
}
else
{
insert(ch[x][A[x] < y], x, y, z);
C[x] = C[ch[x][0]] + C[ch[x][1]] + (bool)B[x];
}
}
void get(int &x, int y)
{
for (int i = x;; i = ch[i][A[i] < y])
{
if (A[i] == y) { Splay(i, 0); x = i; break; }
}
}
void merge(int &x, int y)
{
if (!y) return;
if (B[y]) { insert(x, 0, A[y], B[y]); get(x, A[y]); }
merge(x, ch[y][0]);
merge(x, ch[y][1]);
}
}solve;

void dfs(int x, int fa)
{
solve.insert(t[x] = 0, 0, col[x], 1);
solve.get(t[x], col[x]);
loop(i, ft[x], nt)
{
if (u[i] == fa) continue;
dfs(u[i], x);
ans[v[i]] = solve.C[t[u[i]]];
if (solve.C[t[u[i]]] > solve.C[t[x]])
{
solve.merge(t[u[i]], t[x]);
t[x] = t[u[i]];
}
else solve.merge(t[x], t[u[i]]);
}
}

int main()
{
while (scanf("%d", &n) != EOF)
{
solve.clear(); sz = 0;
rep(i, 1, n) cnt[i] = 0, ft[i] = -1;
rep(i, 1, n) { in(col[i]); cnt[col[i]]++; }
rep(i, 1, n - 1)
{
in(x); in(y);
u[sz] = y; v[sz] = i; nt[sz] = ft[x]; ft[x] = sz++;
u[sz] = x; v[sz] = i; nt[sz] = ft[y]; ft[y] = sz++;
}
dfs(1, 0);
rep(i, 1, n - 1) printf("%d\n", ans[i]);
}
return 0;
}