zoukankan      html  css  js  c++  java
  • 【BZOJ】2733: [HNOI2012]永无乡

    【题意】给定n个岛屿和排名,q次操作,连接两个岛屿或查询岛屿所在连通块第k小。

    【算法】平衡树(treap)||线段树合并

    对于每个连通块维护排名树,启发式合并(将size较小的树一一拆出来加入另一棵树)。

    复杂度O(n log2n)。

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<stack>
    using namespace std;
    const int maxn=100010;
    struct tree{int l,r,rnd,sz,num,id;}t[maxn*2];
    stack<int>s;
    int rank[maxn],fa[maxn],root[maxn],n,m;
    int read(){
        char c;int s=0,t=1;
        while(!isdigit(c=getchar()))if(c=='-')t=-1;
        do{s=s*10+c-'0';}while(isdigit(c=getchar()));
        return s*t;
    }
    void up(int k){t[k].sz=t[t[k].l].sz+1+t[t[k].r].sz;}
    void rturn(int &k){
        int o=t[k].l;
        t[k].l=t[o].r;
        t[o].r=k;
        up(k);up(o);
        k=o;
    }
    void lturn(int &k){
        int o=t[k].r;
        t[k].r=t[o].l;
        t[o].l=k;
        up(k);up(o);
        k=o;
    }
    void insert(int &k,int x){
        if(!k){
            k=s.top();s.pop();
            t[k].rnd=rand();t[k].num=rank[x];
            t[k].sz=1;t[k].l=t[k].r=0;t[k].id=x;
            return;
        }
        t[k].sz++;
        if(rank[x]<t[k].num){
            insert(t[k].l,x);
            if(t[t[k].l].rnd<t[k].rnd)rturn(k);
        }
        else{
            insert(t[k].r,x);
            if(t[t[k].r].rnd<t[k].rnd)lturn(k);
        }
    }
    int getfa(int x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
    void dfs(int k,int &x){
        if(!k)return;
        s.push(k);
        int L=t[k].l,R=t[k].r;
        insert(x,t[k].id);
        dfs(L,x);dfs(R,x);
    }
    void merge(int x,int y){
        x=getfa(x);y=getfa(y);
        if(x==y)return;
        if(t[root[x]].sz<t[root[y]].sz)swap(x,y);
        fa[y]=x;
        dfs(root[y],root[x]);
    }
    int find(int k,int x){
        if(x==t[t[k].l].sz+1)return t[k].id;
        else if(x<t[t[k].l].sz+1)return find(t[k].l,x);
        else return find(t[k].r,x-t[t[k].l].sz-1);
    }
    int main(){
        srand(233);
        n=read();m=read();
        for(int i=1;i<=n;i++)rank[i]=read();
        for(int i=n;i>=1;i--)s.push(i);
        for(int i=1;i<=n;i++)insert(root[i],i);
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=m;i++){
            int x=read(),y=read();
            merge(x,y);
        }
        int Q=read();
        char ch[10];
        for(int i=1;i<=Q;i++){
            scanf("%s",ch);
            int x=read(),y=read();
            if(ch[0]=='B')merge(x,y);
            else{
                if(t[root[getfa(x)]].sz>=y)printf("%d
    ",find(root[fa[x]],y));//use root[]
                else printf("-1
    ");
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    CSS布局简史
    行块布局(如何理解Display:None,Block,Inline,Inline-Block)
    JQuery的基础学习
    在网页中添加一个可以收藏的功能
    PHPcms需要用到
    TP框架里面当访问不存在的操作方法时让其不显示错误页面(空控制器空操作)
    验证码上传文件
    关于API
    webapp的学习
    在ThinkPHP里面进行表单验证
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7906118.html
Copyright © 2011-2022 走看看