zoukankan      html  css  js  c++  java
  • [HNOI 2012]永无乡

    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

    题解

    之前写了个$splay$一直错的没改过来...

    最近喻队让我用线段树合并写这道题,嗯...不错,样例调对了$1A$。

    指针党表示这种动态存储的数据结构都直接上指针...

     1 //It is made by Awson on 2017.10.20
     2 #include <set>
     3 #include <map>
     4 #include <cmath>
     5 #include <ctime>
     6 #include <stack>
     7 #include <queue>
     8 #include <vector>
     9 #include <string>
    10 #include <cstdio>
    11 #include <cstdlib>
    12 #include <cstring>
    13 #include <iostream>
    14 #include <algorithm>
    15 #define LL long long
    16 #define Min(a, b) ((a) < (b) ? (a) : (b))
    17 #define Max(a, b) ((a) > (b) ? (a) : (b))
    18 #define Abs(x) ((x) < 0 ? (-(x)) : (x))
    19 using namespace std;
    20 const int N = 100000;
    21 
    22 int n, m, a, b;
    23 char opt[10];
    24 int val[N+5], id[N+5];
    25 struct node {
    26     int key;
    27     node* child[2];
    28 }sgm[N*20], *root[N+5], *pos = sgm;
    29 struct segment {
    30     void insert(node* &o, int l, int r, int loc) {
    31         if (o == NULL) o = pos++;
    32         if (l == r) {
    33             o->key = 1; return;            
    34         }
    35         int mid = (l+r)>>1;
    36         if (loc <= mid) insert(o->child[0], l, mid, loc);
    37         else insert(o->child[1], mid+1, r, loc);
    38         o->key = 0;
    39         if (o->child[0]) o->key += o->child[0]->key;
    40         if (o->child[1]) o->key += o->child[1]->key;
    41     }
    42     node* merge(node* a, node* b) {
    43         if (!b || !a) return a ? a : b;
    44         a->child[0] = merge(a->child[0], b->child[0]);
    45         a->child[1] = merge(a->child[1], b->child[1]);
    46         a->key = 0;
    47         if (a->child[0]) a->key += a->child[0]->key;
    48         if (a->child[1]) a->key += a->child[1]->key;
    49         return a;
    50     }
    51     int query(node* o, int l, int r, int kth) {
    52         if (l == r) return l;
    53         int mid = (l+r)>>1;
    54         if (!o->child[0]) return query(o->child[1], mid+1, r, kth);
    55         if (o->child[0]->key >= kth) return query(o->child[0], l, mid, kth);
    56         return query(o->child[1], mid+1, r, kth-o->child[0]->key);
    57     }
    58 }T;
    59 int fa[N+5];
    60 int find(int r) {
    61     return fa[r] ? fa[r] = find(fa[r]) : r;
    62 }
    63 
    64 void work() {
    65     scanf("%d%d", &n, &m);
    66     for (int i = 1; i <= n; i++) {
    67         scanf("%d", &val[i]); id[val[i]] = i;
    68     }
    69     for (int i = 1; i <= n; i++) T.insert(root[i], 1, n, val[i]);
    70     while (m--) {
    71         scanf("%d%d", &a, &b);
    72         int q = find(a), p = find(b);
    73         if (p != q) {
    74             root[q] = T.merge(root[p], root[q]);
    75             fa[p] = q;
    76         }
    77     }
    78     scanf("%d", &m);
    79     while (m--) {
    80         scanf("%s%d%d", &opt, &a, &b);
    81         if (opt[0] == 'B') {
    82             int q = find(a), p = find(b);
    83             if (p != q) {
    84                 root[q] = T.merge(root[p], root[q]);
    85                 fa[p] = q;
    86             }
    87         }else {
    88             int q = find(a);
    89             if (b > root[q]->key) printf("-1
    ");
    90             else printf("%d
    ", id[T.query(root[q], 1, n, b)]);
    91         }
    92     }
    93 }
    94 int main() {
    95     work();
    96     return 0;
    97 }
  • 相关阅读:
    windows xp查看缩略图时有缩略图没有文件名
    数据库的相关操作
    使用timer控件创建一个简单的报警程序
    xp_sendmail的正确配置与使用
    SQL Server 索引结构及其使用(三)
    启动与关闭服务器
    不间断连续图片滚动效果的制作方法
    使用C#调用外部Ping命令获取网络连接情况
    SQL Server 索引结构及其使用(一)
    winform 与asp.net 下拉列表的区别
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7701354.html
Copyright © 2011-2022 走看看