列表

详情


NC23807. DongDong数颜色

描述

DongDong是个喜欢数颜色的女孩子,她已经熟练地掌握了在序列上数颜色的操作,现在她开始学习如何在树上数颜色,现在给定一个n个点,n-1条边的树形图(视1号店为根),每个点有一个颜色,每次询问以x为根的子树中有多少种不同的颜色,DongDong轻松地解决了这个问题,但她想考考会编程的你。

输入描述

第一行两个整数n,m

第二行n个整数,表示每个点的颜色

接下来n-1行每行u,v,表示存在一条从u到v的双向边(保证最终图形是树形图)

2<=n<=100000,1<=m,color<=n,

输出描述

共m行:每行输出相应询问的答案

示例1

输入:

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

输出:

3
2
1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 381ms, 内存消耗: 63484K, 提交时间: 2019-06-08 14:36:45

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int M=1e5+10;
int ans[M],timing=0,n,m,co[M];
vector<int>v[M];
set<int>s[M];
void dfs(int x,int fa){
	for(int i=0;i<v[x].size();i++){
		int q=v[x][i];
		if(q==fa)continue;
		dfs(q,x);
		for(set<int>::iterator it=s[q].begin();it!=s[q].end();++it){
			s[x].insert(*it);
		}

	}
	s[x].insert(co[x]);
	ans[x]=s[x].size();
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d",&co[i]);
	for(int i=1,x,y;i<n;i++){
		scanf("%d%d",&x,&y);
		v[x].push_back(y);
		v[y].push_back(x);
	}
	dfs(1,1);
	while(m--){
		int x;
		scanf("%d",&x);
		printf("%d\n",ans[x]);
	}
	return 0;
}

C++(g++ 7.5.0) 解法, 执行用时: 394ms, 内存消耗: 63500K, 提交时间: 2023-03-20 01:25:33

#include<bits/stdc++.h>
using namespace std;

set<int>T[100005];
set<int>::iterator it;
vector<int>R[100005];
int ans[100005],V[100005];
void DFS(int x,int fa)
{
	int i,j;
	for(i=0;i<R[x].size();i++)
	{
		j=R[x][i];
		if(j==fa)continue;
		DFS(j,x);
		for(it=T[j].begin();it!=T[j].end();it++)T[x].insert(*it);
	}
	T[x].insert(V[x]),ans[x]=T[x].size();
}
int main()
{
    int i,j,k,n,m;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)scanf("%d",&V[i]);
    for(i=0;i<n-1;i++)scanf("%d%d",&j,&k),R[j].push_back(k),R[k].push_back(j);
    DFS(1,0);
    while(m--)scanf("%d",&i),printf("%d\n",ans[i]);
    return 0;
}

C++(clang++11) 解法, 执行用时: 256ms, 内存消耗: 11828K, 提交时间: 2020-12-01 15:50:59

#include<set>
#include<vector>
#include<cstdio>
using namespace std;typedef set<int> S;int A[100010],C[100010],n,m,s,t,j;vector<int>G[100010];S d(int a,int v){S s,r;r.insert(C[a]);for(int i=0;i<G[a].size();i++){if(G[a][i]!=v){s=d(G[a][i],a);r.insert(s.begin(),s.end());}}A[a]=r.size();return r;}int main(){scanf("%d%d",&n,&m);for(j=1;j<=n;j++){scanf("%d",&C[j]);}for(j=0;j<n-1;j++){scanf("%d%d",&s,&t);G[s].push_back(t);G[t].push_back(s);}d(1,0);for(j=0;j<m;j++){scanf("%d",&t);printf("%d\n",A[t]);}return 0;}

pypy3 解法, 执行用时: 1198ms, 内存消耗: 72788K, 提交时间: 2023-03-30 16:53:16

n,m = map(int,input().split())
v = list(map(int,input().split()))
has = [[] for _ in range(n)]
for _ in range(n-1):
    a,b = map(lambda x:int(x)-1,input().split())
    has[a].append(b)
    has[b].append(a)
ans = [1]*(n)
def dfs(x,p):
    xx = {v[x]}
    for y in has[x]:
        if y == p:continue
        yy = dfs(y,x)
        if len(xx) < len(yy):
            yy,xx = xx,yy
        xx.update(yy)
    ans[x] = len(xx)
    return xx
dfs(0,0)
for _ in range(m):
    print(ans[int(input())-1])

上一题