题意:有T组測试数据。每组数据的N表示有N个城市,接下来的N行里每行给出每一个城市的坐标(0<=x,y<=1000000),然后有M(1<M<200000)个操作,操作有两类,(1)"road A B",表示将城市A和城市B通过一条道路连接,假设A和B原来属于不同的城市群。经过这个操作。A和B就在一个城市群里了。保证每条道路不会和其它道路相交(除了端点A和B)。(2)"line C"。表示查询当穿过y=C的直线,有多少个城市群、这几个城市群一共同拥有多少个城市。

思路:线段树加并查集

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cmath>
  4. #include<cstdlib>
  5. #include<iostream>
  6. #include<algorithm>
  7. #include<vector>
  8. #include<map>
  9. #include<queue>
  10. #include<stack>
  11. #include<string>
  12. #include<map>
  13. #include<set>
  14. #define eps 1e-6
  15. #define LL long long
  16. using namespace std;
  17.  
  18. const int maxn = 100000 + 100;
  19. const int maxl = 1000000 + 10;
  20. const int INF = 0x3f3f3f3f;
  21. int pa[maxn], low[maxn], high[maxn], pos[maxn], node[maxn];
  22. int sumv1[2*maxl], addv1[2*maxl]; //有多少州
  23. int sumv2[2*maxl], addv2[2*maxl];
  24. int n, m;
  25. //pa保存父亲结点,low,high保存该连通分量的上下边界。node保存连通分量中的结点个数
  26. int find(int x) {
  27. if(x != pa[x]) return pa[x] = find(pa[x]);
  28. return x;
  29. }
  30.  
  31. void maintain1(int o, int L, int R) {
  32. int lc = o*2, rc = o*2+1;
  33. sumv1[o] = 0;
  34. if(R > L) { //考虑左右子树
  35. sumv1[o] = sumv1[lc] + sumv1[rc];
  36. }
  37. sumv1[o] += addv1[o] * (R-L+1);//考虑add操作
  38. }
  39. void update1(int o, int L, int R, int v, int yl, int yr) {
  40. int lc = o*2, rc = o*2+1;
  41. if(yl <= L && yr >= R) { //递归边界
  42. addv1[o] += v; //累加边界的add值
  43. } else {
  44. int M = L + (R-L)/2;
  45. if(yl <= M) update1(lc, L, M, v, yl, yr);
  46. if(yr > M) update1(rc, M+1, R, v, yl, yr);
  47. }
  48. maintain1(o, L, R); //递归结束前又一次计算本节点的附加信息
  49. }
  50. int query1(int o, int L, int R, int add, int yl, int yr) {
  51. if(yl <= L && yr >= R) {
  52. return sumv1[o] + add*(R-L+1);
  53. } else {
  54. int ans = 0;
  55. int M = L + (R-L)/2;
  56. if(yl <= M) ans += query1(o*2, L, M, add + addv1[o], yl, yr);
  57. if(yr > M) ans += query1(o*2+1, M+1, R, add + addv1[o], yl, yr);
  58. return ans;
  59. }
  60. }
  61.  
  62. void maintain2(int o, int L, int R) {
  63. int lc = o*2, rc = o*2+1;
  64. sumv2[o] = 0;
  65. if(R > L) { //考虑左右子树
  66. sumv2[o] = sumv2[lc] + sumv2[rc];
  67. }
  68. sumv2[o] += addv2[o] * (R-L+1);//考虑add操作
  69. }
  70. void update2(int o, int L, int R, int v, int yl, int yr) {
  71. int lc = o*2, rc = o*2+1;
  72. if(yl <= L && yr >= R) { //递归边界
  73. addv2[o] += v; //累加边界的add值
  74. } else {
  75. int M = L + (R-L)/2;
  76. if(yl <= M) update2(lc, L, M, v, yl, yr);
  77. if(yr > M) update2(rc, M+1, R, v, yl, yr);
  78. }
  79. maintain2(o, L, R); //递归结束前又一次计算本节点的附加信息
  80. }
  81. int query2(int o, int L, int R, int add, int yl, int yr) {
  82. if(yl <= L && yr >= R) {
  83. return sumv2[o] + add*(R-L+1);
  84. } else {
  85. int ans = 0;
  86. int M = L + (R-L)/2;
  87. if(yl <= M) ans += query2(o*2, L, M, add + addv2[o], yl, yr);
  88. if(yr > M) ans += query2(o*2+1, M+1, R, add + addv2[o], yl, yr);
  89. return ans;
  90. }
  91. }
  92.  
  93. void init() {
  94. memset(addv1, 0 ,sizeof(addv1)); memset(addv2, 0, sizeof(addv2));
  95. memset(sumv1, 0, sizeof(sumv1)); memset(sumv2, 0, sizeof(sumv2));
  96. cin >> n;
  97. for(int i = 0; i < n; i++) {
  98. int tmp; cin >> tmp >> pos[i];
  99. }
  100. for(int i = 0; i < n; i++) {
  101. pa[i] = i;
  102. node[i] = 1;
  103. high[i] = low[i] = pos[i];
  104. }
  105. cin >> m;
  106. }
  107.  
  108. void solve() {
  109. char cmd[5];
  110. int a, b;
  111. float c;
  112. while(m--) {
  113. cin >> cmd;
  114. if(cmd[0] == 'r') {
  115. cin >> a >> b;
  116. if(find(a) != find(b)) {
  117. if(high[pa[a]] != low[pa[a]]) {
  118. update1(1, 1, 1000000, -1, low[pa[a]]+1, high[pa[a]]);
  119. update2(1, 1, 1000000, -node[pa[a]], low[pa[a]]+1, high[pa[a]]);
  120. }
  121. if(high[pa[b]] != low[pa[b]]) {
  122. update1(1, 1, 1000000, -1, low[pa[b]]+1, high[pa[b]]);
  123. update2(1, 1, 1000000, -node[pa[b]], low[pa[b]]+1, high[pa[b]]);
  124. }
  125. node[pa[a]] += node[pa[b]];
  126. low[pa[a]] = min(low[pa[a]], low[pa[b]]);
  127. high[pa[a]] = max(high[pa[a]], high[pa[b]]);
  128. pa[pa[b]] = pa[a];
  129. if(high[pa[a]] != low[pa[a]]) {
  130. update1(1, 1, 1000000, 1, low[pa[a]]+1, high[pa[a]]);
  131. update2(1, 1, 1000000, node[pa[a]], low[pa[a]]+1, high[pa[a]]);
  132. }
  133. }
  134. } else {
  135. cin >> c;
  136. cout << query1(1, 1, 1000000, 0, (int)(c+1), (int)(c+1)) << " ";
  137. cout << query2(1, 1, 1000000, 0, (int)(c+1), (int)(c+1)) << endl;
  138. // cout << (int)(c+1) << endl;
  139. }
  140. }
  141. }
  142.  
  143. int main() {
  144. // freopen("input.txt", "r", stdin);
  145. int t; cin >> t;
  146. while(t--) {
  147. init();
  148. solve();
  149. }
  150. return 0;
  151. }

uvalive 4730王国kingdom(并查集+线段树)的更多相关文章

  1. UVA1455 - Kingdom(并查集 + 线段树)

    UVA1455 - Kingdom(并查集 + 线段树) 题目链接 题目大意:一个平面内,给你n个整数点,两种类型的操作:road x y 把city x 和city y连接起来,line fnum ...

  2. 并查集&线段树&树状数组&排序二叉树

    超级无敌巨牛逼并查集(带权并查集)https://vjudge.net/problem/UVALive-4487 带删点的加权并查集 https://vjudge.net/problem/UVA-11 ...

  3. 【Codeforces576E_CF576E】Painting Edges(可撤销并查集+线段树分治)

    题目 CF576E 分析: 从前天早上肝到明天早上qwq其实颓了一上午MC ,自己瞎yy然后1A,写篇博客庆祝一下. 首先做这题之前推荐一道很相似的题:[BZOJ4025]二分图(可撤销并查集+线段树 ...

  4. BZOJ 3910 并查集+线段树合并

    思路: 1. 并查集+线段树合并 记得f[LCA]==LCA的时候 f[LCA]=fa[LCA] 2.LCT(并不会写啊...) //By SiriusRen #include <cstdio& ...

  5. 并查集 + 线段树 LA 4730 Kingdom

    题目传送门 题意:训练指南P248 分析:第一个操作可以用并查集实现,保存某集合的最小高度和最大高度以及城市个数.运用线段树成端更新来统计一个区间高度的个数,此时高度需要离散化.这题两种数据结构一起使 ...

  6. YYHS-猜数字(并查集/线段树维护)

    题目描述     LYK在玩猜数字游戏.    总共有n个互不相同的正整数,LYK每次猜一段区间的最小值.形如[li,ri]这段区间的数字的最小值一定等于xi.     我们总能构造出一种方案使得LY ...

  7. luogu5012 水の数列 (并查集+线段树)

    如果我们能求出来每个区间个数的最大分值,那就可以用线段树维护这个东西 然后出答案了 然后这个的求法和(luogu4269)Snow Boots G非常类似,就是我们把数大小排个序,每次都拿<=x ...

  8. 【CF471E】MUH and Lots and Lots of Segments 扫描线+并查集+线段树+set

    [CF471E]MUH and Lots and Lots of Segments 题意:给你平面上n条水平或竖直的,端点在整点处的线段.你需要去掉一些线段的一些部分,使得剩下的图形:1.连通,2.无 ...

  9. bzoj 3237 连通图 - 并查集 - 线段树

    Input Output Sample Input 4 5 1 2 2 3 3 4 4 1 2 4 3 1 5 2 2 3 2 1 2 Sample Output Connected Disconne ...

随机推荐

  1. ActiveMQ学习笔记(15)----Message Dispatch高级特性(一)

    1. Message Cursors 1.1 概述 ActiveMQ发送持久化消息的典型的厝里方式是:当消息的消费者准备就绪时,消息发送系统把存储的消息按批次发送给消费者,在发送完一个批次的消息后,指 ...

  2. QT+OpenCV进行图像采集最小时延能够达到20ms

    得到“算法高性能”项目的支持,目前成功地在Win10上运行WB2,感觉目前的代码速度慢.响应慢.CPU占用比例高.这种情况下3399上能够运行,说明这个平台已经是很强的了.下一步,首先在Windows ...

  3. No mapping found for HTTP request with URI [/spring_liu/hello.do] in DispatcherServlet with name 'SpringMVC'

    控制台一直报No mapping found for HTTP request with URI [/spring_liu/hello.do] in DispatcherServlet with na ...

  4. 洛谷P2770 航空路线问题 最小费用流

    Code: #include<cstdio> #include<iostream> #include<algorithm> #include<vector&g ...

  5. HDU 6315 Naive Operations(线段树+复杂度均摊)

    发现每次区间加只能加1,最多全局加\(n\)次,这样的话,最后的答案是调和级数为\(nlogn\),我们每当答案加1的时候就单点加,最多加\(nlogn\)次,复杂度可以得当保证. 然后问题就是怎么判 ...

  6. [USACO10FEB]吃巧克力Chocolate Eating

    题目:洛谷P2985. 题目大意:有n块巧克力要吃d天,并且只能按顺序吃.一块巧克力有一个开心值,吃了就能增加开心值.一个人初始开心值为0,且每天早上开心值变为原来的一半.问如何吃巧克力才能使开心值最 ...

  7. VMware exsi 虚拟化嵌套

    默认情况下exsi 虚拟化嵌套是没开启的 需要我们连接exsi主机,从后台找到对应的虚拟机修改配置文件开启虚拟化功能 1.连接exsi主机,开启ssh功能 2.ssh到exsi主机,修改配置文件 查找 ...

  8. jQuery第四课 点击 _选项卡效果一

    //鼠标移到上面是显示手型cursor:pointer jquery 的函数: siblings //兄弟节点,同胞元素 :eq()选择器选取带有指定 index 值的元素.index 值从 0 开始 ...

  9. crontab执行脚本和手动执行脚本输出结果不一致的问题处理

    背景:huskiesir最近用公司给分配的账户写了脚本去检测某应用状态并发送到企业邮箱,写完脚本之后去执行了一下,发现效果还不错,在邮箱显示效果如下: 10.11.116.6  检查结果OK,检查时间 ...

  10. poj3134 Power Calculus IDA*

    好端端的一道搜索题目,,,硬生生的被我弄成了乱搞题,,,枚举当前的maxd,深搜结果,然而想到的剪枝方法都没有太好的效果,,,最后用一个贪心乱搞弄出来了,,, 贪心:每次必用上一次做出来的数字与其他数 ...