zoukankan      html  css  js  c++  java
  • 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
    ",ans[i]);
        return 0;
    }
    
    

      

  • 相关阅读:
    LeetCode 224. 基本计算器 栈 双指针
    LeetCode 150. 逆波兰表达式求值 栈
    LeetCode 387. 字符串中的第一个唯一字符 哈希
    LeetCode 316. 去除重复字母 栈 哈希
    LeetCode 44. 通配符匹配 dp
    禁止屏幕旋转并同时解决以至于导致Activity重启的方法
    让振动器振动起来——Vibrator的使用
    简单的JDBC封装
    js jquery ajax 清除ie下的缓存问题
    angular.js 下拉框选中 根据后台返回值
  • 原文地址:https://www.cnblogs.com/mybing/p/8613383.html
Copyright © 2011-2022 走看看