【题目描述】

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

【输入格式】

输入文件第一行是用空格隔开的两个正整数 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

【输出格式】

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

【样例输入】

  5  1           4  3 2 5 1        1  2           7Q 3 2           Q 2 1 B 2 3 B 1 5 Q 2 1 Q 2 4 Q 2 3 

【样例输出】

  -12512
启发式合并么。。。用并查集维护岛屿之间的连通性,并打上size标记来维护岛屿集合的大小。用log数据结构维护每个岛屿集合的所有重要度排名。合并的时候把小的集合暴力插入到大的集合里。这样的话每次合并后大小至少乘以二。最多乘log次,所以最后复杂度是nlog^2n(大概吧。。。)。

平衡树看起来都很难写啊。。。于是并没有写平衡树。。。01trie还是很好的。。。注意到n不超过10W。。。也就是说树的最大深度就是17咯。。。平衡树的最大深度也是1吧。。。所以跑进了rank10???至于01trie怎么合并。。。看置顶的那篇文章吧(神奇的log合并)。。。STL的list是个坑。。。splice、size操作就是O(n)的。。。所以手写了一个链表。。。(也就是说key值的合并是O(1)的了。。。当然没什么用。。。毕竟还有O(nlogn)的插入操作。。。)不过这么说的话vector似乎就行了???注意垃圾清理啊。。。不然内存要开O(nlog^2n)了(大概)。。。会MLE的(亲测,如果前面的假设没有错的话。。。)。。。

拍照留念?


  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <list>
  7
  8 using namespace std;
  9
 10 const int N = 100010;
 11
 12 int n, m, q, x, y, id[N];
 13 char op[10];
 14
 15 int GC[N], gcp;
 16
 17 int keys[N], hd[N], nxt[N], lst[N];
 18
 19 int root[N], ch[N * 20][2], sum[N * 20];
 20
 21 int New() {
 22     static int cnt = 0;
 23     if(gcp) {
 24         int rt =GC[gcp --];
 25         if(rt[ch][0]) {
 26             GC[++ gcp] = rt[ch][0];
 27         }
 28         if(rt[ch][1]) {
 29             GC[++ gcp] = rt[ch][1];
 30         }
 31         rt[ch][0] = rt[ch][1] = 0;
 32         rt[sum] = 0;
 33         return rt;
 34     } else {
 35         return ++ cnt;
 36     }
 37 }
 38
 39 #define walk for(int i = 16, t ; (t = (val >> i) & 1), ~i ; i --)
 40
 41 void ins(int rt, int val) {
 42     walk {
 43         if(rt[ch][t] == 0) rt[ch][t] = New();
 44         (rt = rt[ch][t])[sum] ++;
 45     }
 46 }
 47
 48 int kth(int rt, int val) {
 49     int ret = 0;
 50     walk {
 51         if(val > rt[ch][0][sum]) {
 52             val -= rt[ch][0][sum];
 53             ret |= 1 << i;
 54             rt = rt[ch][1];
 55         } else {
 56             rt = rt[ch][0];
 57         }
 58     }
 59     return ret;
 60 }
 61
 62 int acc[N], size[N];
 63
 64 void init(int n) {
 65     for(int i = 1 ; i <= n ; i ++) {
 66         i[acc] = i;
 67         i[size] = 1;
 68     }
 69 }
 70
 71 int find(int x) {
 72     return x == x[acc] ? x : x[acc] = find(x[acc]);
 73 }
 74
 75 void uni(int x, int y) {
 76     x = find(x);
 77     y = find(y);
 78     if(x != y) {
 79         y[size] += x[size];
 80         x[acc] = y;
 81     }
 82 }
 83
 84 void merge(int x, int y) {
 85     x = find(x);
 86     y = find(y);
 87     if(x != y) {
 88         if(x[size] > y[size]) {
 89             swap(x, y);
 90         }
 91         for(int i = x[hd] ; i ; i = nxt[i]) {
 92             ins(y, keys[i]);
 93             if(nxt[i] == 0) {
 94                 y[lst][nxt] = x;
 95                 y[lst] = x[lst];
 96             }
 97         }
 98         GC[++ gcp] = x;
 99         uni(x, y);
100     }
101 }
102
103 int ask(int rt, int k) {
104     rt = find(rt);
105     if(rt[size] < k) {
106         return -1;
107     } else {
108         int res = kth(rt, k);
109         return res[id];
110     }
111 }
112
113 int main() {
114     freopen("bzoj_2733.in", "r", stdin);
115     freopen("bzoj_2733.out", "w", stdout);
116     scanf("%d%d", &n, &m);
117     init(n);
118     for(int i = 1 ; i <= n ; i ++) {
119         i[root] = New();
120     }
121     for(int i = 1 ; i <= n ; i ++) {
122         scanf("%d", &x);
123         x[id] = i;
124         ins(i[root], x);
125         i[keys] = x;
126         i[hd] = i;
127         i[lst] = i;
128     }
129     for(int i = 1 ; i <= m ; i ++) {
130         scanf("%d%d", &x, &y);
131         merge(x, y);
132     }
133     scanf("%d", &q);
134     for(int i = 1 ; i <= q ; i ++) {
135         scanf("%s%d%d", op, &x, &y);
136         if(op[0] == 'B') {
137             merge(x, y);
138         } else {
139             printf("%d\n", ask(x, y));
140         }
141     }
142     return 0;
143 }

手写链表版

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <vector>
  7
  8 #define walk for(int i = 16, t ; (t = (val >> i) & 1), ~i ; i --)
  9
 10 using namespace std;
 11
 12 const int N = 100010;
 13
 14 int n, m, q, x, y, id[N];
 15
 16 char op[10];
 17
 18 int GC[N], gcp;
 19
 20 vector<int> keys[N];
 21
 22 int root[N], ch[N * 20][2], sum[N * 20];
 23
 24 int acc[N], size[N];
 25
 26 int New() {
 27     static int cnt = 0;
 28     if(gcp) {
 29         int rt =GC[gcp --];
 30         if(rt[ch][0]) {
 31             GC[++ gcp] = rt[ch][0];
 32         }
 33         if(rt[ch][1]) {
 34             GC[++ gcp] = rt[ch][1];
 35         }
 36         rt[ch][0] = rt[ch][1] = 0;
 37         rt[sum] = 0;
 38         return rt;
 39     } else {
 40         return ++ cnt;
 41     }
 42 }
 43
 44 void ins(int rt, int val) {
 45     walk {
 46         if(rt[ch][t] == 0) rt[ch][t] = New();
 47         (rt = rt[ch][t])[sum] ++;
 48     }
 49 }
 50
 51 int kth(int rt, int val) {
 52     int ret = 0;
 53     walk {
 54         if(val > rt[ch][0][sum]) {
 55             val -= rt[ch][0][sum];
 56             ret |= 1 << i;
 57             rt = rt[ch][1];
 58         } else {
 59             rt = rt[ch][0];
 60         }
 61     }
 62     return ret;
 63 }
 64
 65 void init(int n) {
 66     for(int i = 1 ; i <= n ; i ++) {
 67         i[acc] = i;
 68         i[size] = 1;
 69     }
 70 }
 71
 72 int find(int x) {
 73     return x == x[acc] ? x : x[acc] = find(x[acc]);
 74 }
 75
 76 void uni(int x, int y) {
 77     x = find(x);
 78     y = find(y);
 79     if(x != y) {
 80         y[size] += x[size];
 81         x[acc] = y;
 82     }
 83 }
 84
 85 void merge(int x, int y) {
 86     x = find(x);
 87     y = find(y);
 88     if(x != y) {
 89         if(x[size] > y[size])
 90             swap(x, y);
 91         for(int i = 0 ; i < x[keys].size() ; i ++) {
 92             ins(y, x[keys][i]);
 93             y[keys].push_back(x[keys][i]);
 94         }
 95         GC[++ gcp] = x;
 96         uni(x, y);
 97     }
 98 }
 99
100 int ask(int rt, int k) {
101     rt = find(rt);
102     if(rt[size] < k) {
103         return -1;
104     } else {
105         int res = kth(rt, k);
106         return res[id];
107     }
108 }
109
110 int main() {
111     freopen("bzoj_2733.in", "r", stdin);
112     freopen("bzoj_2733.out", "w", stdout);
113
114     scanf("%d%d", &n, &m);
115     init(n);
116     for(int i = 1 ; i <= n ; i ++) {
117         i[root] = New();
118     }
119
120     for(int i = 1 ; i <= n ; i ++) {
121         scanf("%d", &x);
122         x[id] = i;
123         ins(i[root], x);
124         i[keys].push_back(x);
125     }
126
127     for(int i = 1 ; i <= m ; i ++) {
128         scanf("%d%d", &x, &y);
129         merge(x, y);
130     }
131
132     scanf("%d", &q);
133
134     for(int i = 1 ; i <= q ; i ++) {
135         scanf("%s%d%d", op, &x, &y);
136         if(op[0] == 'B') {
137             merge(x, y);
138         } else {
139             printf("%d\n", ask(x, y));
140         }
141     }
142     return 0;
143 }

vector版



转载于:https://www.cnblogs.com/KingSann/articles/7351284.html

cogs 1341 永无乡相关推荐

  1. [bzoj2733]永无乡 [bzoj1503]郁闷的出纳员

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1321  Solved: 693 [Submit][Stat ...

  2. BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]

    2733: [HNOI2012]永无乡 题意:加边,询问一个连通块中k小值 终于写了一下splay启发式合并 本题直接splay上一个节点对应图上一个点就可以了 并查集维护连通性 合并的时候,把siz ...

  3. 数据结构之线段树合并——永无乡,Lomsat gelral,Tree Rotations,Tree Rotations Escape Through Leaf

    文章目录 [HNOI2012]永无乡 Lomsat gelral 「POI2011 R2 Day2」旋转树木 Tree Rotations Escape Through Leaf 线段树合并与 fhq ...

  4. 数据结构之fhq-treap——Chef and Sets,[HNOI2012]永无乡,Play with Chain,[NOI2005]维修数列(结构体版代码)

    因为非常板,所以主要是代码 Tyvj 1728 普通平衡树 Chef and Sets [HNOI2012]永无乡 Play with Chain [NOI2005]维修数列 题目很水,所以可能会出现 ...

  5. P3224 [HNOI2012]永无乡(并查集+权值线段树合并/平衡树)

    [HNOI2012]永无乡 Code1 权值线段树天然支持merge,线段树上二分求第k小 #include<bits/stdc++.h>using namespace std; usin ...

  6. bzoj2733永无乡

    永无乡 HYSBZ - 2733 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接, ...

  7. BZOJ 2733: [HNOI2012]永无乡 启发式合并treap

    2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  8. bzoj 2733: [HNOI2012]永无乡(线段树启发式合并)

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 3850  Solved: 2061 [Submit][Sta ...

  9. [BZOJ2733] [HNOI2012] 永无乡 (splay启发式合并)

    Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以 ...

最新文章

  1. HTTPS网络加密双向验证-使用AFNetworking封装
  2. 文件查找命令find的使用
  3. Hadoop源码分析-Context
  4. centos8中一键安装Nginx
  5. Hadoop动态扩容,增加节点
  6. 15行代码AC——1019 数字黑洞 (20分) 甲级1069. The Black Hole of Numbers (20)(解题报告)
  7. 一个很不错的LINUX基本操作归纳
  8. BAT执行DOS命令查找本地浏览器
  9. NVelocity标签设置缓存的解决方案
  10. C++基础部分_C++文件操作_二进制文件的写操作---C++语言工作笔记078
  11. 一次weblogic 在aix hacmp上调试过程
  12. linux进程号转换成16进制,linux-shell 脚本转换 十六进制 十进制 八进制 二进制
  13. golang ide 下载
  14. java 关键字 assert的学习
  15. GitHub 总星 4w+!删库?女装?表情包?这些沙雕中文项目真是我每天快乐的源泉!
  16. cgb2111-day02
  17. Web安全工具大集合
  18. 集成测试最全详解,看完必须懂了
  19. 从博客搭建和装修学到的东西
  20. (九五至尊)九大管理体系,五大过程组:软考高级信息系统项目管理师

热门文章

  1. 计算机竞赛的数学知识,可以参加的数学类和计算机类竞赛有哪些?
  2. 文字图片OCR识别神器 没有不能复制的文字
  3. Sox语音转换的相关知识
  4. 1月10日前未完成《创业创新执行力》考试的补救措施
  5. T/CAGIS 1—2019《空间三维模型数据格式》
  6. Qt安装及配置资源链接
  7. 请看今日之域中,竟是谁家之天下!-----------2021 年 7 月 TIOBE 指数,“三国争霸”最终谁能登顶?他们的命运掌握在各位大佬的手中
  8. access vba表字段_ACCESS VBA编程(使用技巧大全)[].doc
  9. 我的编程之路:「懒惰」是程序员最大的美德
  10. Predict Binding Sites of Transcription Factor 富集分析