zoukankan      html  css  js  c++  java
  • bzoj2733: [HNOI2012]永无乡 启发式合并

    地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2733

    题目:

    2733: [HNOI2012]永无乡

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 4059  Solved: 2167
    [Submit][Status][Discuss]

    Description

    永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛。如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的。现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥。Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请你输出那个岛的编号。 
     

    Input

    输入文件第一行是用空格隔开的两个正整数 n 和 m,分别 表示岛的个数以及一开始存在的桥数。接下来的一行是用空格隔开的 n 个数,依次描述从岛 1 到岛 n 的重要度排名。随后的 m 行每行是用空格隔开的两个正整数 ai 和 bi,表示一开始就存 在一座连接岛 ai 和岛 bi 的桥。后面剩下的部分描述操作,该部分的第一行是一个正整数 q, 表示一共有 q 个操作,接下来的 q 行依次描述每个操作,操作的格式如上所述,以大写字母 Q 或B 开始,后面跟两个不超过 n 的正整数,字母与数字以及两个数字之间用空格隔开。 对于 20%的数据 n≤1000,q≤1000 
     
    对于 100%的数据 n≤100000,m≤n,q≤300000 
     

    Output

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

    Sample Input

    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

    Sample Output

    -1
    2
    5
    1
    2
     
    思路:
      启发式合并。
      1 /**************************************************************
      2     Problem: 2733
      3     User: weeping
      4     Language: C++
      5     Result: Accepted
      6     Time:4908 ms
      7     Memory:4436 kb
      8 ****************************************************************/
      9  
     10 #include <bits/stdc++.h>
     11  
     12 using namespace std;
     13  
     14 #define lc ch[x][0]
     15 #define rc ch[x][1]
     16  
     17 int n,m,q,f[100005];
     18  
     19 int fd(int x)
     20 {
     21     return f[x]==x?x:f[x]=fd(f[x]);
     22 }
     23  
     24 struct SplayTree
     25 {
     26  
     27     const static int maxn = 1e5 + 15;
     28  
     29     int tot,root,ch[maxn][2], key[maxn], val[maxn], sz[maxn], rev[maxn], fa[maxn];
     30  
     31     inline void init( int x, int ky, int v = 0, int par = 0 )
     32     {
     33         lc=rc=0, fa[x]= par, key[x] = ky, val[x] = v, sz[x] = 1, rev[x] = 0;
     34     }
     35  
     36     inline void init()
     37     {
     38         init( 0, 0, 0 );
     39         sz[0] = 0;
     40         tot = root = 0 ;
     41     }
     42  
     43     inline void push_up(int x)
     44     {
     45         sz[x] = sz[lc] + sz[rc] + 1;
     46     }
     47  
     48     inline void reverse(int x)
     49     {
     50         rev[x] ^= 1, swap( lc, rc);
     51     }
     52  
     53     inline void push_down(int x)
     54     {
     55         if(rev[x])
     56         {
     57             if(lc)  reverse(lc);
     58             if(rc)  reverse(rc);
     59             rev[x] = 0;
     60         }
     61     }
     62  
     63     void rotate( int x)
     64     {
     65         int f = fa[x], gf = fa[f];
     66         int t1 = (ch[f][1] == x), t2 = (ch[gf][1] == f);
     67         if( gf ) ch[gf][t2] = x;
     68         fa[x] = gf, ch[f][t1] = ch[x][1^t1], fa[ch[f][t1]] = f;
     69         ch[x][t1^1] = f, fa[f] = x;
     70         push_up( f ), push_up( x );
     71     }
     72  
     73     void splay( int x, int tar )
     74     {
     75         for(int f = fa[x], gf = fa[f]; f != tar; rotate(x), f = fa[x], gf = fa[f])
     76         if(gf != tar)
     77             rotate( ((ch[f][1] == x) == (ch[gf][1] == f) )? f: x);
     78         if( !tar ) root = x;
     79     }
     80  
     81     void insert( int ky, int v)
     82     {
     83         int x = root, ls = root;
     84         while(x)
     85         {
     86             push_down(x);
     87             sz[x] ++, ls = x;
     88             x = ch[x][ky > key[x]];
     89         }
     90         init( ++tot, ky, v, ls);
     91         ch[ls][ky > key[ls]] = tot;
     92         splay( tot, 0);
     93     }
     94  
     95     int find( int ky)
     96     {
     97         int x = root;
     98         while(x)
     99         {
    100             push_down(x);
    101             if(key[x] == ky) break;
    102             x = ch[x][ky > key[x]];
    103         }
    104         if(x)   splay(x,0);
    105         else x = -1;
    106         return x;
    107     }
    108  
    109     // Delete Root
    110     void Delete()
    111     {
    112         if( !ch[root][0] )
    113         {
    114             fa[ ch[root][1] ] = 0 ;
    115             root = ch[root][1];
    116         }
    117         else
    118         {
    119             int cur = ch[root][0];
    120             while( ch[cur][1] ) cur = ch[cur][1];
    121             splay( cur, root );
    122             ch[cur][1] = ch[root][1];
    123             root = cur, fa[cur] = 0, fa[ch[root][1]] = root;
    124             push_up( root );
    125         }
    126     }
    127  
    128     int kth( int k)
    129     {
    130         int x = root;
    131         if(sz[x] < k) return -1;
    132         while(x)
    133         {
    134             push_down(x);
    135             if(k == sz[lc] + 1) break;
    136             if(k > sz[lc])
    137                 k -= sz[lc] + 1, x = rc;
    138             else
    139                 x = lc;
    140         }
    141         if(x)   splay(x,0);
    142         else x = -1;
    143         return x;
    144     }
    145  
    146     int pred( void)
    147     {
    148         int x = root;
    149         if(!x || !lc)   return -1;
    150         x = lc;
    151         while(rc)    push_down(x), x = rc;
    152         splay( x, 0);
    153         return x;
    154     }
    155  
    156     int succ( void)
    157     {
    158         int x = root;
    159         if(!x || !rc) return -1;
    160         x = rc;
    161         while(lc)   push_down(x), x = lc;
    162         splay( x, 0);
    163         return x;
    164     }
    165  
    166     void debug( int x )
    167     {
    168         if( !x ) return;
    169         if(lc) debug( lc );
    170         printf("%d ", key[x] );
    171         if(rc) debug( rc );
    172     }
    173  
    174     void qinsert(int y)
    175     {
    176         int x = root, ls = root, ky = key[y];
    177         while(x)
    178             ls = x, x = ch[x][ky > key[x]];
    179         x = ls;
    180         ch[x][ky > key[x]] = y,fa[y] = x, sz[y] = 1;
    181         splay(y, 0);
    182     }
    183  
    184     void qmerge(int x)
    185     {
    186         if(!x) return;
    187         int tl = lc, tr = rc;
    188         lc  = rc = 0;
    189         qmerge(tl);
    190         qinsert(x);
    191         qmerge(tr);
    192     }
    193     void merge(int u,int v)
    194     {
    195         if(u == v) return ;
    196         if(sz[u]>sz[v]) swap(u,v);
    197         f[u] = v, splay( v, 0);
    198         qmerge(u);
    199     }
    200 } sp;
    201  
    202  
    203 int main(void)
    204 {
    205     scanf("%d%d",&n,&m);
    206     for(int i=1,x;i<=n;i++)
    207         scanf("%d",&x),f[i]=i,sp.key[i]=x,sp.sz[i]=1;
    208     for(int i=1,u,v;i<=m;i++)
    209         scanf("%d%d",&u,&v),sp.merge(fd(u),fd(v));
    210     scanf("%d",&q);
    211     char op[5];
    212     for(int i=1,x,y;i<=q;i++)
    213     {
    214         scanf("%s%d%d",op,&x,&y);
    215         if(op[0]=='B')
    216             sp.merge(fd(x),fd(y));
    217         else
    218             sp.splay(x,0),printf("%d
    ",sp.kth(y));
    219     }
    220     return 0;
    221 }
  • 相关阅读:
    14 break
    13 for循环
    Python 3.7 将引入 dataclass 装饰器
    工程师如何在面试中脱颖而出
    如何避免 async/await 地狱
    命令行里打 cd 简直是浪费生命
    GitHub 十大 CI 工具
    GitHub CEO:GitHub 十年,感谢有你
    如何在 2 分钟内入睡(二战时期美国飞行员训练法)
    一分钟了解 TCP/IP 模型
  • 原文地址:https://www.cnblogs.com/weeping/p/7662458.html
Copyright © 2011-2022 走看看