• BZOJ 2733 [HNOI2012]永无乡 ——线段树 并查集


    用并查集维护联通块。

    用线段树的合并来合并联通块。

    自己YY了一个写法。

    #include <map>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define ll long long
    #define mp make_pair
    #define maxn 150005
     
     
    int ls[maxn<<5],rs[maxn<<5],rt[maxn];
    int fa[maxn],n,m,tot,sum[maxn<<5],q; char opt[11];
     
    void modify(int o1,int &o2,int l,int r,int x,int f)
    {
        o2=++tot;sum[o2]=sum[o1]+f;if(l==r)return;int mid=l+r>>1;
        if (x<=mid) rs[o2]=rs[o1],modify(ls[o1],ls[o2],l,mid,x,f);
        else ls[o2]=ls[o1],modify(rs[o1],rs[o2],mid+1,r,x,f);
    }
     
    int gf(int k)
    {
        if (fa[k]==k) return k;
        else return fa[k]=gf(fa[k]);
    }
     
    int merge(int o1,int o2,int l,int r)
    {
        if (!(o1*o2)) return o1+o2;
        int mid=l+r>>1;sum[o1]+=sum[o2];
        ls[o1]=merge(ls[o1],ls[o2],l,mid);
        rs[o1]=merge(rs[o1],rs[o2],mid+1,r);
        return o1;
    }
     
    int query(int o,int l,int r,int x)
    {
        if (sum[o]<x) return -1;
        if (l==r) return l;
        int mid=l+r>>1;
        if (x<=sum[ls[o]]) return query(ls[o],l,mid,x);
        else return query(rs[o],mid+1,r,x-sum[ls[o]]);
    }
     
    void Debug(int o,int l,int r)
    {
        if (!o) return ;
        printf(" %d %d == %d
    ",l,r,sum[o]);
        if (l==r) return ;
        Debug(ls[o],l,l+r>>1);
        Debug(rs[o],(l+r>>1)+1,r);
    }
     
    int list[maxn];
     
    int main()
    {
        scanf("%d%d",&n,&m);
        F(i,1,n) fa[i]=i,rt[i]=0;
        F(i,1,n)
        {
            int x;
            scanf("%d",&x);
            modify(rt[i],rt[i],1,n,x,1);
            list[x]=i;
        }
        F(i,1,m)
        {
            int x,y,fx,fy; scanf("%d%d",&x,&y);
            fx=gf(x);fy=gf(y);
            if (fx==fy) continue;
            else
                fa[fy]=fx,rt[fx]=merge(rt[fx],rt[fy],1,n);
        }
        scanf("%d",&q);
        F(i,1,q)
        {
            int x,y,fx,fy,tmp;
            scanf("%s%d%d",opt,&x,&y);
            switch(opt[0])
            {
                case 'Q':
                    fx=gf(x);
                    tmp=query(rt[fx],1,n,y);
                    printf("%d
    ",tmp==-1?-1:list[query(rt[fx],1,n,y)]);
                break;
                case 'B':
                    fx=gf(x);fy=gf(y);
                    if (fx!=fy)
                    {
                        fa[fy]=fx;
                        rt[fx]=merge(rt[fx],rt[fy],1,n);
                    }
                break;
            }
        }
    }
    

      

  • 相关阅读:
    underscorejs
    使用CORS:跨域两三事
    line-height的小技巧
    深入探讨ES6生成器
    ES6生成器基础
    响应式网页
    javascript代码复用(四)-混入、借用方法和绑定
    javascript代码复用模式(三)
    javascript代码复用模式(二)
    jQuery基础事件
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6739803.html
Copyright © 2020-2023  润新知