首页 > 其他 > 详细

bzoj3545: [ONTAK2010]Peaks 主席树合并

时间:2018-03-20 23:33:48      阅读:209      评论:0      收藏:0      [点我收藏+]

排序以后,做并茶几+主席树合并维护,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 主席树合并

原文:https://www.cnblogs.com/mybing/p/8613383.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!