思路:
1.用前向星建图,然后先把树处理成区间;
2.对询问按右边界排序,将权重离散化;
3.离线处理,sum[k]记录k~i之间的k次权值数;
4.每次将k次的段+1,k+1次的段-1.
ACcode:
#include<cstdio>
#include<vector>
#include<iostream>
#include<algorithm>
using std::vector;
using std::sort;
const int nsize=111111;
int n,q,pos;
int *p[nsize];
int a[nsize],num[nsize];
int sum[nsize<<2],cov[nsize<<2];
int e[nsize<<1],next[nsize<<1],head[nsize];
vector<int> lst[nsize];
struct Line
{
int l,r;
} line[nsize];
struct qry
{
int id,l,r;
bool operator <(const qry &cmp) const{
return r<cmp.r;
}
} qry[nsize];
void dfs(int rt)
{
num[rt]=1;
line[rt].l=pos;
for (int i=head[rt]; i>0; i=next[i])
if (!num[e[i]]) pos++,dfs(e[i]);
line[rt].r=pos;
}
void build(int rt,int l,int r)
{
sum[rt]=cov[rt]=0;
if (l==r) return ;
int m=(l+r)>>1;
build(rt<<1,l,m);
build(rt<<1|1,m+1,r);
}
bool cmp(int *a1,int *a2)
{
return *a1<*a2;
}
void PushDown(int rt)
{
sum[rt<<1]+=cov[rt];
cov[rt<<1]+=cov[rt];
sum[rt<<1|1]+=cov[rt];
cov[rt<<1|1]+=cov[rt];
cov[rt]=0;
}
void update(int rt,int l,int r,int L,int R,int v)
{
if (L<=l&&r<=R)
{
sum[rt]+=v;
cov[rt]+=v;
return ;
}
if (cov[rt]) PushDown(rt);
int m=(l+r)>>1;
if (L<=m) update(rt<<1,l,m,L,R,v);
if (R>m) update(rt<<1|1,m+1,r,L,R,v);
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
int query(int rt,int l,int r,int ps)
{
if (l==r) return sum[rt];
if (cov[rt]) PushDown(rt);
int m=(l+r)>>1;
if (ps<=m) return query(rt<<1,l,m,ps);
else return query(rt<<1|1,m+1,r,ps);
}
void add(int u,int v,int i)
{
e[i]=v;
next[i]=head[u];
head[u]=i;
}
int main()
{
int T,cas=0;
int k,i,j,u,v,rt,top;
scanf("%d",&T);
while (T--)
{
scanf("%d %d",&n,&k);
for (top=i=1; i<=n; i++)
{
scanf("%d",&a[i]);
p[i]=&a[i];
lst[i].clear();
head[i]=num[i]=0;
}
for (i=1; i<n; i++)
{
scanf("%d %d",&u,&v);
add(u,v,i+i-1);
add(v,u,i+i);
}
pos=1,dfs(1);
scanf("%d",&q);
for (i=1; i<=q; i++)
{
qry[i].id=i;
scanf("%d",&u);
qry[i].l=line[u].l;
qry[i].r=line[u].r;
}
sort(p+1,p+n+1,cmp);
sort(qry+1,qry+q+1);
v=*p[1],*p[1]=1,u=1;
for (i=2; i<=n; i++)
{
if (*p[i]!=v) v=*p[i],u++;
*p[i]=u;
}
build(1,1,n);
for (j=i=1; i<=q; i++)
{
while (j<=qry[i].r&&j<=n)
{
v=a[j];
lst[v].push_back(j);
u=lst[v].size();
if (u==k) update(1,1,n,1,lst[v][u-k],1);
else if (u>k)
{
update(1,1,n,lst[v][u-k-1]+1,lst[v][u-k],1);
update(1,1,n,(u>k+1?lst[v][u-k-2]:0)+1,lst[v][u-k-1],-1);
}
j++;
}
num[qry[i].id]=query(1,1,n,qry[i].l);
}
if (cas) printf("\n");
printf("Case #%d:\n",++cas);
for (i=1; i<=q; i++) printf("%d\n",num[i]);
}
return 0;
}