传送门
五千字的满分作文题目……
大概只有两句话
给出一棵以 1 为根带权有根树
求 对于每个点 除它的子树以外结点权值的mex
画一棵树 我们发现
对于一个点 若其 ans 为 0 则它子树以外不出现 0
同理非零情况
那么 对于所有相同权值的结点的 LCA 到根的路径上 ans 都可能取这个权值
一个显然的做法是 从小到大枚举权值 做 LCA
这样的做法是足够优秀的 LCA 可以用 Tarjan 实现 倍增也够用了
#include
#include
#include
#include
#include
#define oo 2139062143
#define sqr(x) ((x)*(x))
#define lowbit(x) ((x)&(-x))
#define abs(x) (((x)>=0)?(x):(-(x)))
#define max(x,y) (((x)>(y))?(x):(y))
#define min(x,y) (((x)<(y))?(x):(y))
#define fo(i,x,y) for (int i = (x);i <= (y);++ i)
#define fd(i,x,y) for (int i = (x);i >= (y);-- i)
#define fm(i,x) for (int i = las[x];i;i = nex[i])
using namespace std;
typedef double db;
typedef long long ll;
const int N = 1001000;
int n,m,cas;
int x,y;
int las[N],last[N],nex[N],a[N],tot;
int f[N][21],dep[N];
int bz[N],az[N],los[N],ans[N],du[N],d[N];
int read()
{
char ch=getchar();int x=0;
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x;
}
void link(int x,int y)
{
last[++ tot] = y,
nex[tot] = las[x],
las[x] = tot;
}
void bfs()
{
int i,head = 0,tail = 0,x;
fo(i,1,n)
if (!du[i])
d[++ tail] = i;
dep[1] = 1;
while (head < tail)
{
x = d[++ head];
fm(i,x)
{
-- du[last[i]];
if (!du[last[i]]) d[++ tail] = last[i];
f[last[i]][0] = x;
dep[last[i]] = dep[x] + 1;
}
}
}
int lca(int x,int y)
{
if (dep[x] < dep[y]) swap(x,y);
fd(i,20,0)
if (dep[f[x][i]] > dep[y]) x = f[x][i];
if (dep[x] != dep[y]) x = f[x][0];
fd(i,20,0)
if(f[x][i] != f[y][i]) x = f[x][i],y = f[y][i];
if (x != y) return f[x][0];
else return x;
}
int main()
{
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
for (scanf("%d", &cas);cas;cas --)
{
tot=0;
memset(las,0,sizeof(las)); memset(bz,0,sizeof(bz));
memset(ans,255,sizeof(ans)); memset(du,0,sizeof(du));
scanf("%d%d", &n, &m);
fo(i,1,n) a[i] = read();
fd(i,n,1) los[i] = bz[a[i]],bz[a[i]] = i;
fo(i,1,n - 1)
{
int x = read(),y = read();
link(x,y);
++ du[y];
}
bfs();
fo(j,1,20)
fo(i,1,n)
f[i][j] = f[f[i][j - 1]][j - 1];
fo(i,0,m)
{
x = bz[i],y = 0;
if (!x)
{
fo(j,1,n)
if (ans[j] == -1)
ans[j] = i;
break;
}
while (x)
{
if (!y) y = x; else y = lca(y,x);
x = los[x];
}
while (y && ans[y] == -1) ans[y] = i,y = f[y][0];
}
fo(i,1,n)
{
if (ans[i] == -1) printf("0 ");
else printf("%d ",ans[i]);
}
printf("\n");
}
}