Hdu-5438 Boring counting(可持久化线段树)

来源:互联网 发布:盘古ios9.2 for mac 编辑:程序博客网 时间:2024/05/22 10:55

Description

In this problem we consider a rooted tree with N vertices. The vertices are numbered from 1 to N, and vertex 1 represents the root. There are integer weights on each vectice. Your task is to answer a list of queries, for each query, please tell us among all the vertices in the subtree rooted at vertice u, how many different kinds of weights appear exactly K times?

Input

The first line of the input contains an integer T( T<= 5 ), indicating the number of test cases.
For each test case, the first line contains two integers N and K, as described above. ( 1<= N <= 105, 1 <= K <= N )
Then come N integers in the second line, they are the weights of vertice 1 to N. ( 0 <= weight <= 109 )
For next N-1 lines, each line contains two vertices u and v, which is connected in the tree.
Next line is a integer Q, representing the number of queries. (1 <= Q <= 10 5)
For next Q lines, each with an integer u, as the root of the subtree described above.

Output

For each test case, output "Case #X:" first, X is the test number. Then output Q lines, each with a number -- the answer to each query.

Seperate each test case with an empty line.

Sample Input

13 11 2 21 21 33213

Sample Output

Case #1:111题意:静态问区间中出现次数为k的数字的个数。分析:通过dfs序可以将树上的问题转化为区间问题,然后可以通过将操作离线按右端点排序用每次用树状数组更新答案,同样可以用可持久化线段树转换成在线问题。
#include<iostream>#include<string>#include<algorithm>#include<cstdlib>#include<cstdio>#include<set>#include<map>#include<vector>#include<cstring>#include<stack>#include<queue>#define INF 0x3f3f3f3f#define eps 1e-9#define MOD 1000000007#define MAXN 100005using namespace std;typedef long long ll;int T,n,k,q,u,v,cnt,num,dfs_cnt,w[MAXN],fh[MAXN],rd[MAXN],cd[MAXN],rt[MAXN],b[MAXN],sta[MAXN],Next[MAXN],pre[MAXN],temp[MAXN],sum[MAXN];vector <int> G[MAXN];struct Tree{    int ls,rs,lazy;}tr[MAXN*40];void Build(int &node,int l,int r){    node = ++cnt;    tr[node].lazy = 0;    if(l == r) return;    int mid = (l+r) >> 1;    Build(tr[node].ls,l,mid);    Build(tr[node].rs,mid+1,r);}void deal(int &node,int x,int y,int d,int l,int r){    tr[cnt+1] = tr[node];    node = ++cnt;    if(x == l && y == r)    {        tr[node].lazy += d;        return;    }    int mid = (l+r) >> 1;    if(y <= mid) deal(tr[node].ls,x,y,d,l,mid);    else     if(x <= mid)     {        deal(tr[node].ls,x,mid,d,l,mid);        deal(tr[node].rs,mid+1,y,d,mid+1,r);     }     else deal(tr[node].rs,x,y,d,mid+1,r);}int Find(int node,int x,int l,int r){    if(l == r) return tr[node].lazy;    int mid = (l+r)>>1;    if(x <= mid) return tr[node].lazy + Find(tr[node].ls,x,l,mid);    else return tr[node].lazy + Find(tr[node].rs,x,mid+1,r);}void dfs(int u,int fa){    rd[u] = ++dfs_cnt;    fh[dfs_cnt] = u;    for(int v : G[u])     if(v != fa) dfs(v,u);    cd[u] = dfs_cnt;}void Init(){    dfs_cnt = cnt = 0;    memset(rt,0,sizeof(rt));    memset(pre,0,sizeof(pre));    memset(sum,0,sizeof(sum));    memset(Next,0,sizeof(Next));    memset(temp,0,sizeof(temp));    for(int i = 1;i <= n;i++) G[i].clear();}int main(){    scanf("%d",&T);    for(int t = 1;t <= T;t++)    {        Init();        if(t > 1) printf("\n");        printf("Case #%d:\n",t);        scanf("%d%d",&n,&k);        for(int i = 1;i <= n;i++)        {            scanf("%d",&w[i]);            b[i] = w[i];        }        sort(b+1,b+1+n);        for(int i = 1;i <= n;i++) w[i] = lower_bound(b+1,b+1+n,w[i]) - b;        for(int i = 1;i < n;i++)        {            scanf("%d%d",&u,&v);            G[u].push_back(v);            G[v].push_back(u);        }        dfs(1,-1);        Build(rt[0],1,n);        for(int i = 1;i <= n;i++)        {            int color = w[fh[i]];            if(temp[color]) Next[temp[color]] = i;            pre[i] = temp[color];            temp[color] = i;        }        for(int i = 1;i <= n;i++)        {            int color = w[fh[i]];            rt[i] = rt[i-1];            if(!sum[color]) sta[color] = i;            sum[color]++;            if(sum[color] == k) deal(rt[i],1,sta[color],1,1,n);            else             if(sum[color] > k)             {                 deal(rt[i],pre[sta[color]]+1,sta[color],-1,1,n);                 deal(rt[i],sta[color]+1,Next[sta[color]],1,1,n);                 sta[color] = Next[sta[color]];             }        }        scanf("%d",&q);        for(int i = 1;i <= q;i++)        {            scanf("%d",&num);            printf("%d\n",Find(rt[cd[num]],rd[num],1,n));        }    }}



0 0
原创粉丝点击