[hdu][4358][Boring counting]

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4358

题解:先将树形结构转化成线性结构,这样问题就可以转化为求一个区间内,恰好出现K次的权值有多少种。利用树状数组记录K次的种数(还要用到栈外挂。。。)

View Code
#pragma comment(linker, "/STACK:1024000000,1024000000")

#include <cstdio>

#include <cstring>

#include <map>

#include <vector>

#include <algorithm>



#define clr(a,b) memset(a,b,sizeof(a))

using namespace std;



const int N = 100010;



struct node{

    int x, y, id;

    bool operator < (const node& a)const{

        return y < a.y;

    }

}qn[N];



int s[N], n, k, cnt;

int e, r, he[N], w[N], val[N];

int ev[N*2], nxt[N*2];

int pre[N], ans[N];

int le[N], ri[N];



vector<int>pl[N];

map<int,int>mp;



int lowbit(int a){ return a&(-a); }



void insert(int a, int v){

    while (a<=n){

        s[a] += v;

        a += lowbit(a);

    }

}



int query(int a){

    int res = 0;

    while (a){

        res += s[a];

        a -= lowbit(a);

    } return res;

}



void init(){

    cnt = e = r = 0;

    clr(he, -1); clr(s,0);

    mp.clear();

}



void add(int u, int v){

    ev[e]=v, nxt[e]=he[u], he[u]=e++;

}



void dfs(int u, int fa){

    le[u]=ri[u]=++r; val[r]=w[u];

    for (int i=he[u]; i!=-1; i=nxt[i]){

        if (ev[i]==fa) continue;

        dfs(ev[i], u); ri[u]=ri[ev[i]];

    }

}



int main()

{

    //freopen("D:/a.txt", "r", stdin);

    int T, q, cas=1;

    scanf("%d", &T);

    while (T--){

        scanf("%d%d", &n, &k);

        init();

        for (int i=1; i<=n; i++){

            scanf("%d", &w[i]);

            if (!mp.count(w[i])){

                mp[w[i]]=++cnt;

                pl[cnt].clear();

                pl[cnt].push_back(0);

            }

            w[i]=mp[w[i]];

        }

        for (int i=1; i<n; i++){

            int u, v;

            scanf("%d%d", &u, &v);

            add(u, v), add(v, u);

        }

        dfs(1,1);

        scanf("%d", &q);

        for (int i=1; i<=q; i++){

            int a;

            scanf("%d", &a);

            qn[i].x = le[a];

            qn[i].y = ri[a];

            qn[i].id = i;

        }

        sort(qn+1, qn+1+q);

        int t=1;

        for (int i=1; i<=n; i++){

            int v = val[i]; pl[v].push_back(i);

            int g = pl[v].size()-1;

            if (g >= k){

                if (g > k){

                    insert(pl[v][g-k-1]+1,-1);

                    insert(pl[v][g-k]+1,1);

                }

                insert(pl[v][g-k]+1, 1);

                insert(pl[v][g-k+1]+1, -1);

            }

            while (qn[t].y==i){

                ans[qn[t].id]=query(qn[t].x);

                t++;

            }

        }

        if (cas>1) puts("");

        printf("Case #%d:\n", cas++);

        for (int i=1; i<=q; i++)

            printf("%d\n", ans[i]);

    }

    return 0;

}

你可能感兴趣的:(count)