zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    理解Mysql prepare预处理语句
    php观察折模式
    RSA加密解密
    64位CentOS 6.4下安装wine(32位)
    wireshark安装
    linux安装Vmware的时候出现“Could not open /dev/vmmon”
    php中的魔术方法
    lnmp安装--php安装
    XZ压缩最新压缩率之王
    package.json文件
  • 原文地址:https://www.cnblogs.com/nigel0913/p/2632018.html
Copyright © 2011-2022 走看看