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
  • 相关阅读:
    记录下Cookie与Session
    宝塔部署 springboot 项目遇到的 一些bug处理方案
    [IDEA] [SpringBoot] 项目所写的内容不能同步到编译出的文件中
    cookie和session的区别
    JVM类加载
    线程与线程池
    子父类继承相关(static)
    界面控件开发包DevExpress 9月正式发布v21.1.6
    Delphi开发工具DevExpress VCL全新发布v21.1.5
    强大的Visual Studio插件CodeRush v21.1.7已正式发布
  • 原文地址:https://www.cnblogs.com/ZGQblogs/p/10864359.html
Copyright © 2011-2022 走看看