zoukankan      html  css  js  c++  java
  • P3224 [HNOI2012]永无乡

    题目描述

    永无乡包含 n 座岛,编号从 1n ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 n 座岛排名,名次用 1n 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛到达另一个岛。如果从岛 a 出发经过若干座(含 0 座)桥可以 到达岛 b ,则称岛 a 和岛 b 是连通的。

    现在有两种操作:

    B x y 表示在岛 x 与岛 y 之间修建一座新桥。

    Q x k 表示询问当前与岛 x 连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪座,请你输出那个岛的编号。

    输入输出格式

    输入格式:

    第一行是用空格隔开的两个正整数 nm ,分别表示岛的个数以及一开始存在的桥数。

    接下来的一行是用空格隔开的 n 个数,依次描述从岛 1 到岛 n 的重要度排名。随后的 m 行每行是用空格隔开的两个正整数 aibi ,表示一开始就存在一座连接岛 ai和岛 bi的桥。

    后面剩下的部分描述操作,该部分的第一行是一个正整数 q ,表示一共有 q 个操作,接下来的 q行依次描述每个操作,操作的 格式如上所述,以大写字母 QB 开始,后面跟两个不超过 n 的正整数,字母与数字以及两个数字之间用空格隔开。

    输出格式:

    对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表示所询问岛屿的编号。如果该岛屿不存在,则输出 −1

    输入输出样例

    输入样例#1: 
    5  1
    4  3 2 5 1
    1  2
    7
    Q 3 2
    Q 2 1
    B 2 3
    B 1 5
    Q 2 1
    Q 2 4
    Q 2 3
    输出样例#1: 
    -1
    2
    5
    1
    2

    说明

    对于 20% 的数据 n≤1000,q≤1000

    对于 100% 的数据 n≤100000,m≤n,q≤300000

    Solution:

      本题操作看完就是一眼题,Spaly码农上线。

      初始时每个节点为一棵splay,然后对于两点的联系,由于各树高均为$log n$级别,所以直接暴力往上跳找到这两点所在的splay的根节点,若不同就启发式合并,把节点数较少的splay暴力插入到节点数多的那棵splay中。至于查询就是裸的第k大值查询了。

      时间复杂度$O(nlog n)$。

    代码:

    /*Code by 520 -- 9.20*/
    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define RE register
    #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
    #define son(x) (x==ch[fa[x]][1])
    using namespace std;
    const int N=500005;
    int n,m,Q[N],tot;
    int root[N],cnt,ch[N][2],fa[N],date[N],id[N],siz[N];
    
    int gi(){
        int a=0;char x=getchar();
        while(x<'0'||x>'9') x=getchar();
        while(x>='0'&&x<='9') a=(a<<3)+(a<<1)+(x^48),x=getchar();
        return a;
    }
    
    il int newnode(int x){date[++cnt]=x;siz[cnt]=1;return cnt;}
    
    il void pushup(int rt){siz[rt]=siz[ch[rt][0]]+siz[ch[rt][1]]+1;}
    
    il void rotate(int x){
        int y=fa[x],z=fa[y],b=son(x),c=son(y),a=ch[x][!b];
        if(z) ch[z][c]=x; fa[x]=z;
        if(a) fa[a]=y; ch[y][b]=a;
        fa[y]=x,ch[x][!b]=y;
        pushup(y),pushup(x);
    }
    
    il void splay(int x,int i){
        while(fa[x]!=i) {
            int y=fa[x],z=fa[y];
            if(z==i) rotate(x),fa[x]=i;
            else {
                if(son(x)==son(y)) rotate(y),rotate(x);
                else rotate(x),rotate(x);
            }
        }
    }
    
    int getfa(int x){return !fa[x]?x:getfa(fa[x]);}
    
    void insert(int &rt,int x){
        if(!rt) {rt=x,siz[x]=1;return;}
        if(date[x]<date[rt]) insert(ch[rt][0],x),fa[ch[rt][0]]=rt;
        else insert(ch[rt][1],x),fa[ch[rt][1]]=rt;
        pushup(rt);
    }
    
    int getrank(int rt,int k){
        if(siz[rt]<k) return -1;
        if(siz[ch[rt][0]]+1==k) return rt;
        if(siz[ch[rt][0]]+1>k) return getrank(ch[rt][0],k);
        else return getrank(ch[rt][1],k-siz[ch[rt][0]]-1);
    }
    
    void dfs(int x){
        if(!x) return ;
        dfs(ch[x][0]),Q[++tot]=x,dfs(ch[x][1]);
    }
    
    il void merge(int x,int y){
        x=getfa(x),y=getfa(y),tot=0;
        if(siz[x]>=siz[y]){
            dfs(y);For(i,1,tot) insert(x,Q[i]),splay(Q[i],0),x=Q[i];
        }
        else {
            dfs(x);For(i,1,tot) insert(y,Q[i]),splay(Q[i],0),y=Q[i];
        }
    }
    
    int main(){
        n=gi(),m=gi();
        int x,y;char s[3];
        For(i,1,n) x=gi(),root[i]=newnode(x);
        while(m--){
            x=gi(),y=gi();
            merge(x,y);
        }
        m=gi();
        while(m--){
            scanf("%s",s),x=gi(),y=gi();
            if(s[0]=='Q') printf("%d
    ",getrank(getfa(x),y));
            else {
                x=getfa(x),y=getfa(y);
                if(x!=y) merge(x,y);
            }
        }
        return 0;
    }
  • 相关阅读:
    CF 142B Tprimes
    CF 231A Team
    poj 2001 Shortest Prefixes ——字典树入门
    hdu 1039 Easier Done Than Said?
    poj 2528 Mayor's posters
    hdu 1061 Rightmost Digit
    poj 2503 Babelfish
    CF271 A. Beautiful Year
    poj 2752
    CF271 B. Prime Matrix
  • 原文地址:https://www.cnblogs.com/five20/p/9688868.html
Copyright © 2011-2022 走看看