zoukankan      html  css  js  c++  java
  • [BZOJ2733] [HNOI2012] 永无乡 (splay启发式合并)

    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

    Solution

      维护多棵$splay$,当遇到合并操作时把节点个数少的那棵树所有节点,一个一个暴力插到另一棵树里

      整体来看,合并操作最坏情况下会进行$nlogn$次插入,所以合并的总复杂度是$O(nlog^2n)$,查询的总复杂度是$O(qlogn)$

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 struct spaly
      4 {
      5     int c[2], fa, siz, val;
      6     int& operator[] (int x)
      7     {
      8         return c[x];
      9     }
     10 }a[100005];
     11 int root[100005], fa[100005], sta[100005], top;
     12 
     13 int getfa(int x)
     14 {
     15     return fa[x] = x == fa[x] ? x : getfa(fa[x]);
     16 }
     17 
     18 void LDR(int u)
     19 {
     20     if(!u) return;
     21     LDR(a[u][0]), sta[++top] = u, LDR(a[u][1]);
     22 }
     23 
     24 void rotate(int &k, int x)
     25 {
     26     int y = a[x].fa, z = a[y].fa, dy = a[y][1] == x;
     27     if(k == y) k = x;
     28     else a[z][a[z][1] == y] = x;
     29     a[y][dy] = a[x][!dy], a[a[x][!dy]].fa = y;
     30     a[x][!dy] = y, a[y].fa = x, a[x].fa = z;
     31     a[y].siz = a[a[y][0]].siz + a[a[y][1]].siz + 1;
     32 }
     33 
     34 void splay(int &k, int x)
     35 {
     36     while(k != x)
     37     {
     38         int y = a[x].fa, z = a[y].fa;
     39         if(k != y)
     40             if(a[y][1] == x ^ a[z][1] == y) rotate(k, x);
     41             else rotate(k, y);
     42         rotate(k, x);
     43     }
     44     a[x].siz = a[a[x][0]].siz + a[a[x][1]].siz + 1;
     45 }
     46 
     47 void insert(int &k, int x)
     48 {
     49     if(!k)
     50     {
     51         k = x, a[x].siz = 1, a[x][0] = a[x][1] = 0;
     52         return;
     53     }
     54     ++a[k].siz;
     55     if(a[x].val < a[k].val)
     56         insert(a[k][0], x), a[a[k][0]].fa = k;
     57     else insert(a[k][1], x), a[a[k][1]].fa = k;
     58 }
     59 
     60 int find_kth(int k, int x)
     61 {
     62     if(!k) return -1;
     63     if(x <= a[a[k][0]].siz) return find_kth(a[k][0], x);
     64     if(x == a[a[k][0]].siz + 1) return k;
     65     return find_kth(a[k][1], x - a[a[k][0]].siz - 1);
     66 }
     67 
     68 void addedge(int u, int v)
     69 {
     70     if(u == v) return;
     71     if(a[root[u]].siz < a[root[v]].siz)
     72         swap(u, v);
     73     fa[v] = u, LDR(root[v]);
     74     while(top)
     75     {
     76         insert(root[u], sta[top]);
     77         splay(root[u], sta[top--]);
     78     }
     79 }
     80 
     81 int main()
     82 {
     83     int n, m, q, u, v;
     84     char op[5];
     85     scanf("%d%d", &n, &m);
     86     for(int i = 1; i <= n; ++i)
     87         scanf("%d", &a[i].val);
     88     for(int i = 1; i <= n; ++i)
     89         root[i] = fa[i] = i, a[i].siz = 1;
     90     while(m--)
     91     {
     92         scanf("%d%d", &u, &v);
     93         addedge(getfa(u), getfa(v));
     94     }
     95     scanf("%d", &q);
     96     while(q--)
     97     {
     98         scanf("%s%d%d", op, &u, &v);
     99         if(op[0] == 'B') addedge(getfa(u), getfa(v));
    100         else printf("%d
    ", find_kth(root[getfa(u)], v));
    101     }
    102     return 0;
    103 }
    View Code
  • 相关阅读:
    http-proxy-middleware与express.json()的bug
    20+前端常用的vscode插件(总结推荐)
    图解翻转单向链表,超详细(python语言实现)
    pytest + allure2.x 踩坑-报告无数据
    Pycharm+pytest+allure打造高逼格的测试报告
    Appium Appium Python API 中文版
    appium模拟键盘事件
    AppiumDesktop控制手机和安卓模拟器
    Appium环境搭建超详细教程
    Fiddler抓包工具总结
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5621938.html
Copyright © 2011-2022 走看看