poj 2104 C - Count on a tree

Posted HelloWorld!--By-MJY

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj 2104 C - Count on a tree相关的知识,希望对你有一定的参考价值。

技术分享
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#include<string.h>

#define MAXN  1000100
#define  ll long long
using namespace std;
#define Mod 998244353

int rt[20*MAXN],ls[20*MAXN],rs[20*MAXN],sum[20*MAXN];
int z[MAXN],b[MAXN];
int sz,cnt;

void Build(int l,int r,int &a)
{
    a=++cnt;
    sum[a]=0;
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    Build(l,mid,ls[a]);
    Build(mid+1,r,rs[a]);
}

void Update(int l,int r,int last,int ind,int &a)
{
    a=++cnt;
    ls[a]=ls[last];
    rs[a]=rs[last];
    sum[a]=sum[last]+1;
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    if(ind<=mid)
        Update(l,mid,ls[a],ind,ls[a]);
    else
        Update(mid+1,r,rs[a],ind,rs[a]);
}

int Ques(int l,int r,int l1,int r1,int k)
{
    if(l==r)
        return l;
    int s=sum[ls[r1]]-sum[ls[l1]];
    int mid=(l+r)>>1;
    if(k<=s)
        return Ques(l,mid,ls[l1],ls[r1],k);
    else
        return Ques(mid+1,r,rs[l1],rs[r1],k-s);
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,q;
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&z[i]);
            b[i]=z[i];
        }
        sort(b+1,b+n+1);
        sz=unique(b+1,b+n+1)-(b+1);
        cnt=0;
        Build(1,sz,rt[0]);
        for(int i=1;i<=n;i++)
            z[i]=lower_bound(b+1,b+sz+1,z[i])-b;//这边是sz 
        for(int i=1;i<=n;i++)
            Update(1,sz,rt[i-1],z[i],rt[i]);
        while(q--)
        {
            int l,r,k;
            scanf("%d%d%d",&l,&r,&k);
            int ans=Ques(1,sz,rt[l-1],rt[r],k);
            printf("%d\n",b[ans]);
        }
    }
    return 0;
}
View Code
技术分享
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#include<string.h>

#define MAXN  200100
#define  ll long long
using namespace std;
#define Mod 998244353

int z[MAXN],b[MAXN],de[MAXN],head[MAXN],rt[MAXN*20],ls[MAXN*20],rs[MAXN*20],sum[MAXN*20],anc[MAXN][25],f[MAXN];
struct node
{
    int v,next;
}edge[MAXN<<1];
int cnt,tot,sz;

void add(int u,int v)
{
    edge[cnt].v=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}


int lca(int a,int b)
{
    if(de[a]<de[b])
        swap(a,b);
    for(int i=22;i>=0;i--)
        if(de[b]<=de[anc[a][i]])
            a=anc[a][i];
    if(a==b)
        return a;
    for(int i=22;i>=0;i--)
        if(anc[a][i]!=anc[b][i])
        {
            a=anc[a][i];
            b=anc[b][i];
        }
    return anc[a][0];
}



void Build(int l,int r,int &a)
{
    a=++tot;
    sum[a]=0;
    int mid=(l+r)>>1;
    if(l==r)
        return ;
    Build(l,mid,ls[a]);
    Build(mid+1,r,rs[a]);
}

void Update(int l,int r,int last,int ind,int &a)
{
    a=++tot;
    ls[a]=ls[last];
    rs[a]=rs[last];
    sum[a]=sum[last]+1;
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    if(ind<=mid)
        Update(l,mid,ls[a],ind,ls[a]);
    else
        Update(mid+1,r,rs[a],ind,rs[a]);
}
void dfs(int u,int fa)
{

    de[u]=de[fa]+1;
    anc[u][0]=fa;
    f[u]=fa;
 // cout<<u<<" "<<fa<<endl;
    Update(1,sz,rt[fa],z[u],rt[u]);
    for(int i=1;i<=22;i++)
        anc[u][i]=anc[anc[u][i-1]][i-1];
    
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==fa)
            continue;
        dfs(v,u);
    }
}

int Ques(int l,int r,int l1,int r1,int lc,int  flc,int k)
{
    if(l==r)
        return l;
    int s=sum[ls[l1]]+sum[ls[r1]]-sum[ls[lc]]-sum[ls[flc]];
    int mid=(l+r)>>1;
    if(k<=s)
        return Ques(l,mid,ls[l1],ls[r1],ls[lc],ls[flc],k);
    else
        return Ques(mid+1,r,rs[l1],rs[r1],rs[lc],rs[flc],k-s);

}

int main()
{
    int n,m;

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&z[i]);
            b[i]=z[i];
        }
        memset(de,0,sizeof(de));
        memset(head,-1,sizeof(head));
        memset(anc,0,sizeof(anc));
        sort(b+1,b+n+1);
        sz=unique(b+1,b+n+1)-(b+1);
        cnt=tot=0;
        Build(1,sz,rt[0]);

        for(int i=1;i<n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        for(int i=1;i<=n;i++)
            z[i]=lower_bound(b+1,b+cnt+1,z[i])-b;
        dfs(1,0);
        while(m--)
        {
            int a,c,k;
            scanf("%d%d%d",&a,&c,&k);
            int d=lca(a,c);
            int ind=Ques(1,sz,rt[a],rt[c],rt[d],rt[f[d]],k);
            printf("%d\n",b[ind]);
        }
    }

    return 0;
}
View Code

 

以上是关于poj 2104 C - Count on a tree的主要内容,如果未能解决你的问题,请参考以下文章

POJ 2777 Count Color (线段树成段更新+二进制思维)

划分树 poj2104 hdu5249

poj2104 求区间第k大 可持久化线段树

POJ2104 K-th Number

poj2104K-th Number (主席树)

POJ_2104_Kth(主席树)