zoukankan      html  css  js  c++  java
  • 【Luogu】P3224永无乡(splay)

      题目链接

      splay模板,启发式合并(其实就是暴力插入)即可。

      顺便吐槽时限,带垃圾回收而已……不至于最后一个点死活不让过吧?

      

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<cctype>
    #include<queue>
    #define maxn 100020
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    int CNT;
    struct Node{
        int val,size,e[2],fa,num;
    }tree[maxn*10];
    int tot;
    
    struct Splay{
        int root;
        Splay(){root=0;}
        inline void update(int x){tree[x].size=tree[tree[x].e[0]].size+tree[tree[x].e[1]].size+1;    }
        inline int iden(int x){    return x==tree[tree[x].fa].e[1];    }
        inline void connect(int x,int fa,int how){    tree[x].fa=fa;    tree[fa].e[how]=x;    }
        void rotate(int x){
            int y=tree[x].fa;    int r=tree[y].fa;
            int sony=iden(x);    int sonr=iden(y);
            if(root==y)    root=x;
            int b=tree[x].e[sony^1];
            connect(b,y,sony);
            connect(y,x,sony^1);
            connect(x,r,sonr);
            update(y);    update(x);
        }
        void splay(int pos,int to){
            to=tree[to].fa;
            while(tree[pos].fa!=to){
                if(tree[tree[pos].fa].fa==to)    rotate(pos);
                else
                    if(iden(pos)==iden(tree[pos].fa)){
                        rotate(tree[pos].fa);
                        rotate(pos);
                    }
                    else{    rotate(pos);    rotate(pos);    }
            }
        }
        inline int create(int val,int num,int fa){
            tree[++tot]=(Node){val,1,{0,0},fa,num};
            return tot;
        }
        int build(int val,int num){
            if(root==0){
                root=create(val,num,0);
                return root;
            }
            int now=root;
            while(now){
                tree[now].size++;
                int nxt=val<tree[now].val?0:1;
                if(tree[now].e[nxt]==0){
                    connect(create(val,num,now),now,nxt);
                    update(now);
                    return tot;
                }
                now=tree[now].e[nxt];
            }
        }
        void insert(int val,int num){
            int p=build(val,num);
            if(++CNT==50){
                splay(p,root);
                CNT=0;
            }
        }
        int rank(int val){
            if(tree[root].size<val)    return -1;
            int now=root;
            while(1){
                if(tree[tree[now].e[0]].size+1==val)    return tree[now].num;
                if(tree[tree[now].e[0]].size>=val)    now=tree[now].e[0];
                else{
                    val-=tree[tree[now].e[0]].size+1;
                    now=tree[now].e[1];
                }
            }
        }
    }s[maxn];
    
    void pushtree(int now,int x){
        s[x].insert(tree[now].val,tree[now].num);
        if(tree[now].e[0])    pushtree(tree[now].e[0],x);
        if(tree[now].e[1])    pushtree(tree[now].e[1],x);
    }
    
    int father[maxn];
    int w[maxn];
    
    int ufind(int x){
        if(father[x]!=x)    father[x]=ufind(father[x]);
        return father[x];
    }
    
    void unionn(int x,int y){
        x=ufind(x);    y=ufind(y);
        if(tree[s[x].root].size<tree[s[y].root].size)    swap(x,y);
        pushtree(s[y].root,x);
        father[y]=x;
    }
    
    int main(){
        int n=read(),m=read();
        for(int i=1;i<=n;++i){
            w[i]=read();
            father[i]=i;
            s[i].insert(w[i],i);
        }
        for(int i=1;i<=m;++i){
            int x=read(),y=read();
            unionn(x,y);
        }
        int p=read();
        for(int i=1;i<=p;++i){
            char c[10];
            scanf("%s",c);
            int x=read(),y=read();
            if(c[0]=='Q')    printf("%d
    ",s[ufind(x)].rank(y));
            else            unionn(x,y);
        }
        return 0;
    }
  • 相关阅读:
    Linux用户和用户组管理
    Linux系统概述
    Linux LVM 配置
    linux too many open files 问题总结
    tidb初体验
    kafka配置内外网访问
    使用docker快速安装软件
    一次ssh不能登陆问题
    kubernetes集群证书更新
    istio之envoy常见术语及状态码
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8358187.html
Copyright © 2011-2022 走看看