bzoj3545: [ONTAK2010]Peaks 主席树合并

Posted mybing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3545: [ONTAK2010]Peaks 主席树合并相关的知识,希望对你有一定的参考价值。

排序以后,做并茶几+主席树合并维护,Orzstdcall,没想到权值线段树的合并竟然是O(nlogn)的...虽然他给我证明了一波,但是还是不是十分理解...听说是Cydiater给他讲的,Orz

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch<=‘9‘&&ch>=‘0‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
struct one
{int x,id,y,v,f;};
one e[2200010];
int f1,f2,n,m,q,cnt=0,root[501000],hash[501000],fa[501000],a[501000],sum[6000000],l[6000000],r[6000000],ans[500100];
bool cmp(one aa,one bb){if(aa.v==bb.v)return aa.f<bb.f;else return aa.v<bb.v;}
void add(int &pre,int L,int R,int x)
{
    if(!pre)pre=++cnt;sum[pre]=1;
    if(L>=R)return;
    int mid=(L+R)>>1;
    if(x<=mid){add(l[pre],L,mid,x);}
    else {add(r[pre],mid+1,R,x);}
}
int getfather(int pp)
{
    if(pp==fa[pp])return pp;
    else return fa[pp]=getfather(fa[pp]);
}
int merge(int aa,int bb)
{
    if(!aa)return bb;
    if(!bb)return aa;
    if((!l[aa])&&(!r[aa]))
    {
        sum[aa]+=sum[bb];
        return aa;
    }
    l[aa]=merge(l[aa],l[bb]);
    r[aa]=merge(r[aa],r[bb]);
    sum[aa]=sum[l[aa]]+sum[r[aa]];
    return aa;
}
int query(int pre,int L,int R,int x)
{
    if(L>=R)return L;
    int mid=(L+R)>>1;
    if(x<=sum[l[pre]])return query(l[pre],L,mid,x);
    else return query(r[pre],mid+1,R,x-sum[l[pre]]);
}
int main()
{
    //freopen("xf.in","r",stdin);
    //freopen("xf.out","w",stdout);
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=n;i++)a[i]=read(),hash[i]=a[i];
    sort(hash+1,hash+n+1);
    for(int i=1;i<=m;i++)
    {
        e[i].x=read();
        e[i].y=read();
        e[i].v=read();
        e[i].f=0;
    }
    for(int i=m+1;i<=m+q;i++)
    {
        e[i].x=read();
        e[i].v=read();
        e[i].y=read();
        e[i].f=1;
        e[i].id=i-m;
    }
    sort(e+1,e+q+m+1,cmp);
    for(int i=1;i<=n;i++)
    {
        int x=lower_bound(hash+1,hash+n+1,a[i])-hash;
        add(root[i],1,n,x);
    }
    for(int i=1;i<=n;i++)fa[i]=i;
    for(int i=1;i<=m+q;i++)
    {
        if(!e[i].f)
        {
            f1=getfather(e[i].x);
            f2=getfather(e[i].y);
            if(f1==f2)continue;
            fa[f1]=f2;
            root[f2]=merge(root[f1],root[f2]);
        }
        else
        {
            f1=getfather(e[i].x);
            if(sum[root[f1]]<e[i].y)ans[e[i].id]=-1;
            else ans[e[i].id]=hash[query(root[f1],1,n,sum[root[f1]]-e[i].y+1)];
        }
    }
    for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
    return 0;
}

  

以上是关于bzoj3545: [ONTAK2010]Peaks 主席树合并的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ3545][ONTAK2010]Peaks

BZOJ 3545ONTAK 2010Peaks & BZOJ 3551ONTAK 2010Peaks加强版 Kruskal重构树

bzoj3545[ONTAK2010]Peaks 线段树合并

Bzoj3545 [ONTAK2010]Peaks

bzoj 3545/3551: [ONTAK2010]Peaks -- 主席树,最小生成树,倍增

bzoj3545: [ONTAK2010]Peaks 主席树合并