• hdu 4358 Boring counting dfs序+莫队+离散化


    Boring counting

    Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 98304/98304 K (Java/Others)


    Problem Description
    In this problem we consider a rooted tree with N vertices. The vertices are numbered from 1 to N, and vertex 1 represents the root. There are integer weights on each vectice. Your task is to answer a list of queries, for each query, please tell us among all the vertices in the subtree rooted at vertice u, how many different kinds of weights appear exactly K times?
     
    Input
    The first line of the input contains an integer T( T<= 5 ), indicating the number of test cases.
    For each test case, the first line contains two integers N and K, as described above. ( 1<= N <= 105, 1 <= K <= N )
    Then come N integers in the second line, they are the weights of vertice 1 to N. ( 0 <= weight <= 109 )
    For next N-1 lines, each line contains two vertices u and v, which is connected in the tree.
    Next line is a integer Q, representing the number of queries. (1 <= Q <= 105)
    For next Q lines, each with an integer u, as the root of the subtree described above.
     
    Output
    For each test case, output "Case #X:" first, X is the test number. Then output Q lines, each with a number -- the answer to each query.

    Seperate each test case with an empty line.
     
    Sample Input
    1 3 1 1 2 2 1 2 1 3 3 2 1 3
     
    Sample Output
    Case #1: 1 1 1
     
    Author
    fish@UESTC_Oblivion
     
    Source
    题意:给你一棵树,n个节点,以1为根,每个节点有一个权值w;
       q个询问,每个询问问,以该点为根的子树下某个权值出现k次的个数;
    思路:首先w很大,用map会超时;需要离散化一下;
       处理子树问题,利用dfs序,改成区间处理;
       区间处理权值出现k次的树,利用莫队得到答案;
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pi (4*atan(1.0))
    #define eps 1e-14
    const int N=1e5+10,M=1e6+10,inf=1e9+10;
    const ll INF=1e18+10,mod=2147493647;
    struct is
    {
        int v,nex;
    }edge[N<<1];
    int head[N<<1],edg,in[N],out[N],tot,pos[N],w[N];
    vector<int>l;
    int a[N],flag[N];
    void add(int u,int v)
    {
        edg++;
        edge[edg].v=v;
        edge[edg].nex=head[u];
        head[u]=edg;
    }
    void dfs(int u,int fa)
    {
        in[u]=++tot;
        for(int i=head[u];i!=-1;i=edge[i].nex)
        {
            int v=edge[i].v;
            if(v==fa)continue;
            dfs(v,u);
        }
        out[u]=tot;
    }
    struct hh
    {
        int l,r,now;
        bool operator <(const hh b)
        {
            if(pos[l]!=pos[b.l])
                return pos[l]<pos[b.l];
            return r<b.r;
        }
    }p[N];
    int ans[N],mp[N],z[N];
    void add(int pos)
    {
        z[mp[a[pos]]]--;
        mp[a[pos]]++;
        z[mp[a[pos]]]++;
    }
    void del(int pos)
    {
        z[mp[a[pos]]]--;
        mp[a[pos]]--;
        z[mp[a[pos]]]++;
    }
    void init(int n)
    {
        l.clear();
        memset(mp,0,sizeof(mp));
        memset(z,0,sizeof(z));
        int s=(int)(sqrt(n));
        for(int i=1;i<=n;i++)
            pos[i]=(i-1)/s+1;
        memset(head,-1,sizeof(head));
        memset(a,0,sizeof(a));
        edg=0;
        tot=0;
    }
    int main()
    {
        int T,cas=1;
        scanf("%d",&T);
        while(T--)
        {
            if(cas!=1)
                printf("
    ");
            int n,k;
            scanf("%d%d",&n,&k);
            init(n);
            for(int i=1;i<=n;i++)
                scanf("%d",&w[i]),l.push_back(w[i]);
            sort(l.begin(),l.end());
            for(int i=1;i<n;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                add(u,v);
                add(v,u);
            }
            dfs(1,-1);
            for(int i=1;i<=n;i++)
                flag[in[i]]=i;
            for(int i=1;i<=n;i++)
                a[i]=lower_bound(l.begin(),l.end(),w[flag[i]])-l.begin();
            int q;
            scanf("%d",&q);
            for(int i=1;i<=q;i++)
            {
                int x;
                scanf("%d",&x);
                p[i].l=in[x];
                p[i].r=out[x];
                p[i].now=i;
            }
            sort(p+1,p+1+q);
            int L=1,R=0;
            for(int i=1;i<=q;i++)
            {
                //cout<<p[i].l<<" "<<p[i].r<<" "<<p[i].now<<endl;
                while(L<p[i].l)
                {
                    del(L);
                    L++;
                }
                while(L>p[i].l)
                {
                    L--;
                    add(L);
                }
                while(R>p[i].r)
                {
                    del(R);
                    R--;
                }
                while(R<p[i].r)
                {
                    R++;
                    add(R);
                }
                ans[p[i].now]=z[k];
            }
            printf("Case #%d:
    ",cas++);
            for(int i=1;i<=q;i++)
                printf("%d
    ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    集算器如何优化SQL计算(2)分组
    集算器如何优化SQL计算(1)动态列
    android DOM解析Xml
    ASP.NET 抓取网页内容
    抓取HTML网页数据
    [转]Android的网络与通信
    Android的三种网络通信方式
    Android通过onDraw实现在View中绘图操作
    Android Canvas类介绍
    DatabaseMetaData的用法(转)
  • 原文地址:https://www.cnblogs.com/jhz033/p/6145276.html
Copyright © 2020-2023  润新知