zoukankan      html  css  js  c++  java
  • CodeForces

    You have a rooted tree consisting of n vertices. Each vertex of the tree has some color. We will assume that the tree vertices are numbered by integers from 1 to n. Then we represent the color of vertex v as cv. The tree root is a vertex with number 1.

    In this problem you need to answer to m queries. Each query is described by two integers vj, kj. The answer to query vj, kj is the number of such colors of vertices x, that the subtree of vertex vj contains at least kj vertices of color x.

    You can find the definition of a rooted tree by the following link: http://en.wikipedia.org/wiki/Tree_(graph_theory).

    Input

    The first line contains two integers n and m (2 ≤ n ≤ 105; 1 ≤ m ≤ 105). The next line contains a sequence of integers c1, c2, ..., cn (1 ≤ ci ≤ 105). The next n - 1lines contain the edges of the tree. The i-th line contains the numbers ai, bi (1 ≤ ai, bi ≤ nai ≠ bi) — the vertices connected by an edge of the tree.

    Next m lines contain the queries. The j-th line contains two integers vj, kj (1 ≤ vj ≤ n; 1 ≤ kj ≤ 105).

    Output

    Print m integers — the answers to the queries in the order the queries appear in the input.

    Examples

    Input
    8 5
    1 2 2 3 3 2 3 3
    1 2
    1 5
    2 3
    2 4
    5 6
    5 7
    5 8
    1 2
    1 3
    1 4
    2 3
    5 3
    Output
    2
    2
    1
    0
    1
    Input
    4 1
    1 2 3 4
    1 2
    2 3
    3 4
    1 1
    Output
    4

    题意:
    给定一颗树,树上的每个节点都有一个颜色,以1为根节点。
    每次询问,问以节点v为根节点的子树里面,有多少种颜色出现次数大于k。
    思路:
    想到莫队之后,dfs序和树状数组很好想了。

    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<map>
    #include<set>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<ctime>
    #define fuck(x) cout<<#x<<" = "<<x<<endl;
    #define debug(a,i) cout<<#a<<"["<<i<<"] = "<<a[i]<<endl;
    #define ls (t<<1)
    #define rs ((t<<1)+1)
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int maxn = 100086;
    const int maxm = 100086;
    const int inf = 2.1e9;
    const ll Inf = 999999999999999999;
    const int mod = 1000000007;
    const double eps = 1e-6;
    const double pi = acos(-1);
    
    int col[maxn];
    int num[maxn];
    int vis[maxn];
    int cnt,Head[maxn];
    int tl[maxn],tr[maxn];
    struct node{
        int v,nxt;
    }e[2*maxn];
    struct query{
        int l,r,id,k;
    }a[maxn];
    
    void add_edge(int u,int v){
        e[cnt].v=v;
        e[cnt].nxt = Head[u];
        Head[u]=cnt++;
    }
    
    void dfs(int u,int fa){
        tl[u]=++cnt;
        num[cnt]=col[u];
        for(int k=Head[u];~k;k=e[k].nxt){
            if(e[k].v!=fa)dfs(e[k].v,u);
        }
        tr[u]=cnt;
    }
    int block;
    bool cmp(query a,query b){
        if(a.l/block!=b.l/block){return a.l<b.l;}
        return a.r<b.r;
    }
    int lowbit(int x){
        return x&-x;
    }
    
    int bit[maxn];
    
    int query(int pos){
        int ans=0;
        while(pos){
            ans+=bit[pos];
            pos-=lowbit(pos);
        }
        return ans;
    }
    
    void update(int pos,int val){
        if(pos<=0){return;}
        while(pos<maxn){
            bit[pos]+=val;
            pos+=lowbit(pos);
        }
    }
    
    int ans[maxn];
    
    int main()
    {
        memset(Head,-1,sizeof(Head));
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&col[i]);
        }
    
        for(int i=1;i<n;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add_edge(x,y);
            add_edge(y,x);
        }
        cnt=0;
        dfs(1,0);
    
        block=sqrt(cnt);
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            a[i].l=tl[x];
            a[i].r=tr[x];
            a[i].k=y;
            a[i].id=i;
        }
    
        sort(a+1,a+1+m,cmp);
        int L=1,R=0;
        for(int i=1;i<=m;i++){
            while(L<a[i].l){
                update(vis[num[L]],-1);
                vis[num[L]]--;
                update(vis[num[L]],1);
                L++;
            }
            while(R<a[i].r){
                R++;
                update(vis[num[R]],-1);
                vis[num[R]]++;
                update(vis[num[R]],1);
            }
            while(L>a[i].l){
                L--;
                update(vis[num[L]],-1);
                vis[num[L]]++;
                update(vis[num[L]],1);
            }
            while(R>a[i].r){
                update(vis[num[R]],-1);
                vis[num[R]]--;
                update(vis[num[R]],1);
                R--;
            }
            ans[a[i].id]=query(maxn-1)-query(a[i].k-1);
        }
        for(int i=1;i<=m;i++){
            printf("%d
    ",ans[i]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Linux下高并发socket最大连接数所受的各种限制
    Oracle DB 使用资源管理
    Oracle DB 资源管理
    C++ 封装私有堆(Private Heap)
    用宏实现 C++ Singleton 模式
    基于 crt debug 实现的 Windows 程序内存泄漏检测工具
    如何养成良好的 C++ 编程习惯 —— 内存管理
    OCP-1Z0-053-V12.02-643题
    Oracle DB 通过SQL 优化管理性能
    OCP-1Z0-052-V8.02-141题
  • 原文地址:https://www.cnblogs.com/ZGQblogs/p/10864359.html
Copyright © 2011-2022 走看看