题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4358
题意:以1为根节点含有N(N <= 1e5)个结点的树,每个节点有一个权值(weight <= 1e9)。之后有m(m <= 1e5)次查询,每次查询以节点u为子树的树中,权值出现k次的权值有多少个?
Sample Input
1
3 1 (n,k)
1 2 2
1 2
1 3
3 (m)
2 1 3
Sample Output
Case #1:
1
1
1
思路:建好树之后,dfs得到L[x],R[x].即将树形结构变成了线性的结构。并且由于问的是权值出现k次的权值有多少个,和权值的大小无关。就可以离散化,在dfs中把节点重新排序,并且重新赋值.(我们只关心dfs序之后的id和val);这样之后直接跑莫队即可;
细节:至于离散化,直接使用了vector和lower_bound()来合并相同的值;之后输入时建好查询的q[]即可.
#pragma comment(linker, "/STACK:1024000000") #include<bits/stdc++.h> using namespace std; #define rep0(i,l,r) for(int i = (l);i < (r);i++) #define rep1(i,l,r) for(int i = (l);i <= (r);i++) #define rep_0(i,r,l) for(int i = (r);i > (l);i--) #define rep_1(i,r,l) for(int i = (r);i >= (l);i--) #define MS0(a) memset(a,0,sizeof(a)) #define MS1(a) memset(a,-1,sizeof(a)) #define MSi(a) memset(a,0x3f,sizeof(a)) #define inf 0x3f3f3f3f #define lson l, m, rt << 1 #define rson m+1, r, rt << 1|1 typedef pair<int,int> PII; #define A first #define B second #define MK make_pair #define pb push_back typedef __int64 ll; template<typename T> void read1(T &m) { T x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} m = x*f; } template<typename T> void read2(T &a,T &b){read1(a);read1(b);} template<typename T> void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);} template<typename T> void out(T a) { if(a>9) out(a/10); putchar(a%10+'0'); } const int M = 100100; int head[M],tot,a[M],dfs_clock; int T,kase = 0,i,j,k,n,m,top,cnt[M]; struct Edge{ int to,w,Next; Edge(){} Edge(int to,int w,int Next):to(to),w(w),Next(Next){} }e[M<<1]; inline void ins(int u,int v,int w = 0) { e[++tot] = Edge{v,w,head[u]}; head[u] = tot; } vector<int> p; void init() { dfs_clock = tot = 0; MS0(head);p.clear(); MS0(cnt); } int L[M],R[M],val[M],ans[M]; void dfs(int u,int pre) { L[u] = ++dfs_clock; val[dfs_clock] = a[u];//关系的只是dfs序之后的序号; for(int d = head[u];d;d = e[d].Next){ int v = e[d].to; if(v == pre) continue; dfs(v,u); } R[u] = dfs_clock; } struct data{ int l,r,id,block; data(){} data(int l,int r,int id,int block):l(l),r(r),id(id),block(block){} }q[M]; bool cmp(const data& a,const data& b) { return a.block - b.block?a.block < b.block:a.r < b.r; } void update(int pos,int add) { if(cnt[val[pos]] == k) top--; else if(cnt[val[pos]] + add == k) top++; cnt[val[pos]] += add; } void solve() { top = 0; for(int i = 1,l = 1,r = 0;i <= m;i++){ while(r < q[i].r) update(++r,1); while(r > q[i].r) update(r--,-1); while(l < q[i].l) update(l++,-1); while(l > q[i].l) update(--l,1); ans[q[i].id] = top; } } int main() { read1(T); while(T--){ init(); read2(n,k); rep1(i,1,n) read1(a[i]),p.pb(a[i]); sort(p.begin(),p.end()); rep1(i,1,n) //离散化; a[i] = lower_bound(p.begin(),p.end(),a[i]) - p.begin(); int u,v; rep0(i,1,n){ read2(u,v); ins(u,v);ins(v,u); } dfs(1,-1); int block = sqrt(n); read1(m); rep1(i,1,m){ read1(u); q[i] = data(L[u],R[u],i,L[u]/block); } sort(q+1,q+1+m,cmp); solve(); if(kase) puts(""); printf("Case #%d: ",++kase); rep1(i,1,m){ out(ans[i]); puts(""); } } return 0; }