[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;
}
原文地址:https://www.cnblogs.com/nigel0913/p/2632018.html