卧薪尝胆,厚积薄发。
Colorful Tree
Date: Tue Feb 26 11:08:36 CST 2019 In Category: NoCategory

Description:

给出一棵树,支持两种操作,将一个点的子树染成一种给定颜色,问一个点的子树里有几种不同的颜色。
$1\leqslant n\leqslant 10^6$

Solution:

我退役吧。

Code:


#include<bits/stdc++.h>
using namespace std;
int n,q;
#define MAXN 100010
inline int rd()
{
register int res = 0,f = 1;register char c = getchar();
while(!isdigit(c)){if(c == '-')f = -1;c = getchar();}
while(isdigit(c))res = (res << 1) + (res << 3) + c - '0',c = getchar();
return res * f;
}
#define re register
#define I inline
struct edge
{
int to,nxt;
}e[MAXN << 1];
int edgenum = 0;
int lin[MAXN] = {0};
I void add(int a,int b)
{
e[++edgenum] = (edge){b,lin[a]};lin[a] = edgenum;
e[++edgenum] = (edge){a,lin[b]};lin[b] = edgenum;
return;
}
#define pii pair<int,int>
int dep[MAXN],fa[MAXN],top[MAXN],son[MAXN],siz[MAXN];
int ind[MAXN],oud[MAXN],th[MAXN],tot = 0;
void dfs1(int k,int depth)
{
ind[k] = ++tot;th[tot] = k;
dep[k] = depth;
siz[k] = 1;son[k] = 0;
for(re int i = lin[k];i != 0;i = e[i].nxt)
{
if(e[i].to == fa[k])continue;
fa[e[i].to] = k;
dfs1(e[i].to,depth + 1);
siz[k] += siz[e[i].to];
if(son[k] == 0 || siz[e[i].to] > siz[son[k]])son[k] = e[i].to;
}
oud[k] = tot;
return;
}
void dfs2(int k,int tp)
{
top[k] = tp;
if(son[k] == 0)return;
dfs2(son[k],tp);
for(re int i = lin[k];i != 0;i = e[i].nxt)
{
if(e[i].to == fa[k] || e[i].to == son[k])continue;
dfs2(e[i].to,e[i].to);
}
return;
}
I int LCA(int a,int b)
{
while(top[a] != top[b])
{
if(dep[top[a]] < dep[top[b]])swap(a,b);
a = fa[top[a]];
}
return (dep[a] < dep[b] ? a : b);
}
int col[MAXN];
struct node
{
int lc,rc;
int val;
}t[MAXN << 1];
int ptr = 0;
I int newnode(){return ++ptr;}
int root;
#define mid ((l + r) >> 1)
void build(int &rt,int l,int r)
{
rt = newnode();t[rt].val = 0;
if(l == r){t[rt].val = col[th[l]];return;}
build(t[rt].lc,l,mid);build(t[rt].rc,mid + 1,r);
return;
}
I void pushdown(int rt)
{
if(t[rt].val)t[t[rt].lc].val = t[t[rt].rc].val = t[rt].val;
t[rt].val = 0;return;
}
void update(int rt,int L,int R,int k,int l,int r)
{
if(L <= l && r <= R){t[rt].val = k;return;}
if(t[rt].val)pushdown(rt);
if(L <= mid)update(t[rt].lc,L,R,k,l,mid);
if(R > mid)update(t[rt].rc,L,R,k,mid + 1,r);
return;
}
int query(int rt,int p,int l,int r)
{
if(l == r)return t[rt].val;
if(t[rt].val)pushdown(rt);
if(p <= mid)return query(t[rt].lc,p,l,mid);
else return query(t[rt].rc,p,mid + 1,r);
}
namespace BIT
{
int c[MAXN];
I int lowbit(int x){return x & (-x);}
I void add(int p,int x)
{
for(re int i = p;i <= n;i += lowbit(i))c[i] += x;
return;
}
I int query(int p)
{
re int res = 0;
for(re int i = p;i >= 1;i -= lowbit(i))res += c[i];
return res;
}
}
set< pii > s,ss[MAXN];
set< pii >::iterator it,it_;
I int calclca(int x)
{//cout << " : " << it -> first << " " << it -> second << endl;
re int x1 = 0,x2 = 0;
if(it != ss[col[x]].begin())x1 = LCA((--(it_ = it)) -> second,x);
if((++(it_ = it)) != ss[col[x]].end())x2 = LCA(it_ -> second,x);
return (dep[x1] > dep[x2] ? x1 : x2);
}
void work()
{
scanf("%d",&n);
edgenum = tot = 0;
re int opt,u,v;
s.clear();
for(re int i = 1;i <= n;++i)lin[i] = 0,ss[i].clear(),BIT::c[i] = 0;
for(re int i = 1;i < n;++i)add(rd(),rd());
dfs1(1,1);dfs2(1,1);
for(re int i = 1;i <= n;++i)
{
col[i] = rd();
ss[col[i]].insert(make_pair(ind[i],i));
s.insert(make_pair(ind[i],i));
}
ptr = 0;
build(root,1,n);
for(re int i = 1,pre = 0;i <= n;++i,pre = 0)
{
for(it = ss[i].begin();it != ss[i].end();++it)
{
BIT::add(it -> first,1);
if(pre)BIT::add(ind[LCA(pre,it -> second)],-1);
pre = it -> second;
}
}
scanf("%d",&q);
for(re int i = 1;i <= q;++i)
{
opt = rd();u = rd();
pii tmp = make_pair(ind[u],u);
if(opt == 0)
{//cout << "st" << endl;
v = rd();
while(true)
{
it = s.lower_bound(tmp);
if(it == s.end() || it -> first > oud[u])break;
re int x = it -> second;
it = ss[col[x]].find(*it);//cout << "sst" << endl;
re int x_ = calclca(x);//cout << it -> first << " " << it -> second << " " << x << " -> " << x_ << endl;//cout << "eed" << endl;
if(x_)BIT::add(ind[x_],1);
BIT::add(ind[x],-1);
pii tmp_ = *it;
s.erase(tmp_);
ss[col[x]].erase(tmp_);
col[x] = v;
}//cout << "ed" << endl;
col[u] = v;
s.insert(tmp);
ss[v].insert(tmp);
it = ss[v].find(tmp);
re int p = calclca(u);
if(p)BIT::add(ind[p],-1);
BIT::add(ind[u],1);
update(root,ind[u],oud[u],v,1,n);
}
else
{
re int ans = BIT::query(oud[u]) - BIT::query(ind[u] - 1);
it = s.lower_bound(tmp);
if(it == s.end())++ans;
else if(it -> second != u)
{
re int color = query(root,ind[u],1,n);
it = ss[color].lower_bound(tmp);
if(it == ss[color].end() || it -> first > oud[u])++ans;
}
printf("%d\n",ans);
}
}
return;
}
int main()
{
int testcases;
scanf("%d",&testcases);
for(int i = 1;i <= testcases;++i)
{
printf("Case #%d:\n",i);
work();
}
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡