• BZOJ2733: [HNOI2012]永无乡


    2733: [HNOI2012]永无乡

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 4426  Solved: 2363
    [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

    HINT

    Source

    【题解】

    不难看出启发式合并。

    我写完之后突然发现。。。。尼玛我TM怎么全程没有用过splay?

    丁队早期的板子有点不靠谱啊。。。

    我查了查才知道。。。

    insert后需要splay(本题不行,除非执行删除节点操作)

    getk需要splay

    ...

    反正啥啥都得splay一下。。

    还好现在发现了,不然命丧IOI2019(???)

      1 /**************************************************************
      2     Problem: 2733
      3     User: 33511595
      4     Language: C++
      5     Result: Accepted
      6     Time:3168 ms
      7     Memory:4808 kb
      8 ****************************************************************/
      9  
     10 #include <iostream>
     11 #include <cstdio>
     12 #include <cstring>
     13 #include <cstdlib>
     14 #include <algorithm>
     15 #include <queue>
     16 #include <vector>
     17 #include <map>
     18 #include <string> 
     19 #include <cmath> 
     20 #define min(a, b) ((a) < (b) ? (a) : (b))
     21 #define max(a, b) ((a) > (b) ? (a) : (b))
     22 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
     23 template <class T>
     24 inline void swap(T& a, T& b)
     25 {
     26     T tmp = a;a = b;b = tmp;
     27 }
     28 inline void read(int &x)
     29 {
     30     x = 0;char ch = getchar(), c = ch;
     31     while(ch < '0' || ch > '9') c = ch, ch = getchar();
     32     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
     33     if(c == '-') x = -x;
     34 }
     35  
     36 const int INF = 0x3f3f3f3f;
     37 const int MAXN = 100000 + 10;
     38 int fa[MAXN], ch[MAXN][2], size[MAXN], cnt[MAXN], data[MAXN], node[MAXN], n, nn, root[MAXN], father[MAXN];
     39 int find(int x)
     40 {
     41     return x == father[x] ? x : father[x] = find(father[x]);
     42 }
     43 int son(int x){return x == ch[fa[x]][1];}
     44 void pushup(int x)
     45 {
     46     size[x] = size[ch[x][0]] + size[ch[x][1]] + cnt[x];
     47 }
     48  
     49 //编号为k的平衡树 
     50 void rotate(int x, int k)
     51 {
     52     int y = fa[x], z = fa[y], b = son(x), c = son(y), a = ch[x][!b];
     53     if(z) ch[z][c] = x; else root[k] = x; fa[x] = z;
     54     if(a) fa[a] = y; ch[y][b] = a;
     55     ch[x][!b] = y, fa[y] = x;
     56     pushup(y), pushup(x);
     57 }
     58  
     59 //编号为k的平衡树 
     60 void splay(int x, int i, int k)
     61 {
     62     while(fa[x] != i)
     63     {
     64         int y = fa[x], z = fa[y];
     65         if(z == i) rotate(x, k);
     66         else
     67             if(son(x) == son(y)) rotate(y, k), rotate(x, k);
     68             else rotate(x, k), rotate(x, k);
     69     }
     70 }
     71  
     72 //编号为k的平衡树 
     73 int getmn(int rt, int k)
     74 {
     75     int ans = -1;
     76     while(rt)
     77     {
     78         ans = rt;
     79         rt = ch[rt][0];
     80     }
     81     if(ans != -1) splay(ans, 0, k);
     82     return ans;
     83 }
     84  
     85 //编号为k的平衡树 
     86 int getkth(int rt, int kk, int k)
     87 {
     88     int l = ch[rt][0];
     89     if(size[l] + 1 <= kk && kk <= size[l] + cnt[rt]) 
     90     {
     91         splay(rt, 0, k);
     92         return rt;
     93     }
     94     else if(size[l] + 1 > kk) return getkth(l, kk, k);
     95     else return getkth(ch[rt][1], kk - size[l] - cnt[rt], k);
     96 }
     97  
     98 //插入节点zz 
     99 void insert(int &rt, int zz)
    100 {
    101     if(rt == 0)
    102     {
    103         rt = zz, size[zz] = 1;
    104         return;
    105     }
    106     if(data[zz] < data[rt]) insert(ch[rt][0], zz), fa[ch[rt][0]] = rt;
    107     else if(data[zz] > data[rt]) insert(ch[rt][1], zz), fa[ch[rt][1]] = rt;
    108     pushup(rt);
    109 }
    110  
    111 //把以x节点为根的树插入到以y节点为根的树上 
    112 void dfs(int x, int y, int k)
    113 {
    114     if(!x) return;
    115     int tmp = y;
    116     insert(tmp, x);
    117     dfs(ch[x][0], y, k);
    118     dfs(ch[x][1], y, k);
    119 }
    120  
    121 //把编号为y的岛与编号为x的岛连接,y插入到x 
    122 void lk(int x, int y)
    123 {
    124     int f1 = find(x), f2 = find(y);
    125     if(f1 == f2) return;
    126     if(size[root[f1]] < size[root[f2]]) swap(f1, f2);
    127     dfs(root[f2], root[f1], f1);
    128     father[f2] = f1;
    129 }
    130  
    131 //查询与x联通的岛中第y重要的岛 
    132 void ask(int x, int y)
    133 {
    134     int t = find(x), tmp = root[t];
    135     if(size[tmp] < y) printf("-1
    ");
    136     else printf("%d
    ", node[getkth(tmp, y, t)]);
    137 }
    138  
    139 int m,q,tmp1,tmp2;
    140 char c;
    141  
    142 int main()
    143 {
    144     read(n);read(m);
    145     for(int i = 1;i <= n;++ i) read(tmp1), father[i] = i, root[i] = i, data[i] = tmp1, node[i] = i, cnt[i] = 1, ++ nn, size[i] = 1;
    146     for(int i = 1;i <= m;++ i) read(tmp1), read(tmp2), lk(tmp1, tmp2);
    147     read(q);
    148     for(int i = 1;i <= q;++ i)
    149     {
    150         scanf("%s", &c), read(tmp1), read(tmp2);
    151         if(c == 'Q') ask(tmp1, tmp2);
    152         else lk(tmp1, tmp2);
    153     }
    154     return 0;
    155 }
    BZOJ2733
  • 相关阅读:
    根据输入的个数,打印每行做多输出3个的for循环
    在启动页面后面再加载一个广告页,可以定制动画等
    frame.size.height无法直接赋值问题
    iOS开发远程推送
    iOS——UIKeyboardWillShowNotification 监听键盘高度变化
    iOS 浅谈本地通知 UILocalNotification
    iOS中assign、copy 、retain等关键字的含义
    GCD
    xocde快速定位崩溃代码
    关于xcode打包app
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8375755.html
Copyright © 2020-2023  润新知