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
  • 相关阅读:
    iOS开发-ScrollView图片缩放
    算法-随机不重复数列生成
    iOS开发-舒尔特表
    iOS开发-音乐播放
    iOS开发-简单的图片查看器
    iOS开发-Interface Builder的前世今生
    iOS开发-DatePicker控件
    iOS开发-UI基础Demo
    Objective-C-Category类别
    Objective-C面向对象之实现类
  • 原文地址:https://www.cnblogs.com/ZGQblogs/p/10864359.html
Copyright © 2011-2022 走看看