题目:

洛谷4219

分析:

很明显,查询的是删掉某条边后两端点所在连通块大小的乘积。

有加边和删边,想到LCT。但是我不会用LCT查连通块大小啊。果断弃了

有加边和删边,还跟连通性有关,于是开始yy线段树分治做法(不知道线段树分治?推荐一个伪模板题BZOJ4025二分图事实上这个链接是指向我的博客的)。把每次操作(加边或查询)看做一个时刻,一条边存在的区间就是它加入后没有被查询的时间区间的并。于是用可撤销并查集维护一下连通块大小即可。

代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cctype>
  4. #include <algorithm>
  5. #include <map>
  6. #include <cassert>
  7. #undef i
  8. #undef j
  9. #undef k
  10. #undef min
  11. #undef max
  12. #undef true
  13. #undef false
  14. #undef swap
  15. #undef sort
  16. #undef if
  17. #undef for
  18. #undef while
  19. #undef printf
  20. #undef scanf
  21. #undef putchar
  22. #undef getchar
  23. #define _ 0
  24. using namespace std;
  25. namespace zyt
  26. {
  27. template<typename T>
  28. inline bool read(T &x)
  29. {
  30. char c;
  31. bool f = false;
  32. x = 0;
  33. do
  34. c = getchar();
  35. while (c != EOF && c != '-' && !isdigit(c));
  36. if (c == EOF)
  37. return false;
  38. if (c == '-')
  39. f = true, c = getchar();
  40. do
  41. x = x * 10 + c - '0', c = getchar();
  42. while (isdigit(c));
  43. if (f)
  44. x = -x;
  45. return true;
  46. }
  47. inline bool read(char &c)
  48. {
  49. do
  50. c = getchar();
  51. while (c != EOF && !isgraph(c));
  52. return c != EOF;
  53. }
  54. template<typename T>
  55. inline void write(T x)
  56. {
  57. static char buf[20];
  58. char *pos = buf;
  59. if (x < 0)
  60. putchar('-'), x = -x;
  61. do
  62. *pos++ = x % 10 + '0';
  63. while (x /= 10);
  64. while (pos > buf)
  65. putchar(*--pos);
  66. }
  67. typedef long long ll;
  68. const int N = 1e5 + 10, B = 17, QUERY = 0, ADD = 1;
  69. int n, q;
  70. ll ans[N];
  71. struct node
  72. {
  73. bool type;
  74. int x, y;
  75. }arr[N];
  76. namespace UFS
  77. {
  78. int fa[N], rk[N], size[N], top;
  79. struct node
  80. {
  81. int x, y, fax, rky, sizey;
  82. }stack[N];
  83. void init(const int n)
  84. {
  85. for (int i = 1; i <= n; i++)
  86. fa[i] = i, rk[i] = size[i] = 1;
  87. }
  88. int f(const int u)
  89. {
  90. return fa[u] == u ? u : f(fa[u]);
  91. }
  92. bool merge(const int u, const int v)
  93. {
  94. int x = f(u), y = f(v);
  95. if (x == y)
  96. return false;
  97. if (rk[x] > rk[y])
  98. swap(x, y);
  99. stack[top++] = (node){x, y, fa[x], rk[y], size[y]};
  100. fa[x] = y, size[y] += size[x];
  101. if (rk[x] == rk[y])
  102. ++rk[y];
  103. return true;
  104. }
  105. int query(const int u)
  106. {
  107. assert(f(u) < N);
  108. return size[f(u)];
  109. }
  110. void undo(const int bck)
  111. {
  112. while (top > bck)
  113. {
  114. --top;
  115. int x = stack[top].x, y = stack[top].y;
  116. assert(x < N && y < N);
  117. fa[x] = stack[top].fax;
  118. rk[y] = stack[top].rky;
  119. size[y] = stack[top].sizey;
  120. }
  121. }
  122. }
  123. namespace Segment_Tree
  124. {
  125. struct edge
  126. {
  127. int x, y, next;
  128. }e[N * (B + 1)];
  129. int head[1 << (B + 1) | 11], ecnt;
  130. inline void init()
  131. {
  132. memset(head, -1, sizeof(head));
  133. }
  134. inline void add(const int a, const int b, const int c)
  135. {
  136. e[ecnt] = (edge){b, c, head[a]}, head[a] = ecnt++;
  137. }
  138. inline void insert(const int rot, const int lt, const int rt, const int ls, const int rs, const int x, const int y)
  139. {
  140. if (ls <= lt && rt <= rs)
  141. {
  142. add(rot, x, y);
  143. return;
  144. }
  145. int mid = (lt + rt) >> 1;
  146. if (ls <= mid)
  147. insert(rot << 1, lt, mid, ls, rs, x, y);
  148. if (rs > mid)
  149. insert(rot << 1 | 1, mid + 1, rt, ls, rs, x, y);
  150. }
  151. inline void solve(const int rot, const int lt, const int rt)
  152. {
  153. int bck = UFS::top;
  154. for (int i = head[rot]; ~i; i = e[i].next)
  155. UFS::merge(e[i].x, e[i].y);
  156. if (lt == rt)
  157. {
  158. if (arr[lt].type == QUERY)
  159. ans[lt] = (ll)UFS::query(arr[lt].x) * UFS::query(arr[lt].y);
  160. UFS::undo(bck);
  161. return;
  162. }
  163. int mid = (lt + rt) >> 1;
  164. solve(rot << 1, lt, mid);
  165. solve(rot << 1 | 1, mid + 1, rt);
  166. UFS::undo(bck);
  167. }
  168. }
  169. map<pair<int, int>, int> lastins;
  170. int work()
  171. {
  172. read(n), read(q);
  173. UFS::init(n);
  174. Segment_Tree::init();
  175. for (int i = 1; i <= q; i++)
  176. {
  177. char opt;
  178. read(opt), read(arr[i].x), read(arr[i].y);
  179. if (arr[i].x > arr[i].y)
  180. swap(arr[i].x, arr[i].y);
  181. arr[i].type = (opt == 'Q' ? QUERY : ADD);
  182. pair<int, int> p = make_pair(arr[i].x, arr[i].y);
  183. if (arr[i].type == ADD)
  184. lastins[p] = i;
  185. else
  186. {
  187. Segment_Tree::insert(1, 1, q, lastins[p], i - 1, p.first, p.second);
  188. lastins[p] = i + 1;
  189. }
  190. }
  191. for (map<pair<int, int>, int>::iterator it = lastins.begin(); it != lastins.end(); it++)
  192. if (it->second <= q)
  193. Segment_Tree::insert(1, 1, q, it->second, q, it->first.first, it->first.second);
  194. Segment_Tree::solve(1, 1, q);
  195. for (int i = 1; i <= q; i++)
  196. if (arr[i].type == QUERY)
  197. write(ans[i]), putchar('\n');
  198. return (0^_^0);
  199. }
  200. }
  201. int main()
  202. {
  203. return zyt::work();
  204. }

【洛谷4219】[BJOI2014]大融合(线段树分治)的更多相关文章

  1. 洛谷4219 BJOI2014大融合(LCT维护子树信息)

    QWQ 这个题目是LCT维护子树信息的经典应用 根据题目信息来看,对于一个这条边的两个端点各自的\(size\)乘起来,不过这个应该算呢? 我们可以考虑在LCT上多维护一个\(xv[i]\)表示\(i ...

  2. 洛谷 P4219 [BJOI2014]大融合 解题报告

    P4219 [BJOI2014]大融合 题目描述 小强要在\(N\)个孤立的星球上建立起一套通信系统.这套通信系统就是连接\(N\)个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的 ...

  3. 洛谷P4219 - [BJOI2014]大融合

    Portal Description 初始有\(n(n\leq10^5)\)个孤立的点,进行\(Q(Q\leq10^5)\)次操作: 连接边\((u,v)\),保证\(u,v\)不连通. 询问有多少条 ...

  4. 洛谷 P4219 [BJOI2014]大融合

    查询,就相当于先删去这条边,然后查询边的两个端点所在连通块大小,乘起来得到答案,然后再把边加回去 可以用线段树分治做 #pragma GCC optimize("Ofast") # ...

  5. 洛谷 P2147 [SDOI2008]洞穴勘测 (线段树分治)

    题目链接 题解 早就想写线段树分治的题了. 对于每条边,它存在于一段时间 我们按时间来搞 我们可把一条边看做一条线段 我们可以模拟线段树操作,不断分治下去 把覆盖\(l-r\)这段时间的线段筛选出来, ...

  6. 洛谷P4219 [BJOI2014]大融合(LCT,Splay)

    LCT维护子树信息的思路总结与其它问题详见我的LCT总结 思路分析 动态连边,LCT题目跑不了了.然而这题又有点奇特的地方. 我们分析一下,查询操作就是要让我们求出砍断这条边后,x和y各自子树大小的乘 ...

  7. 洛谷P4219 [BJOI2014]大融合(LCT)

    LCT维护子树信息的思路总结与其它问题详见我的LCT总结 思路分析 动态连边,LCT题目跑不了了.然而这题又有点奇特的地方. 我们分析一下,查询操作就是要让我们求出砍断这条边后,x和y各自子树大小的乘 ...

  8. 洛谷 P3373 【模板】线段树 2

    洛谷 P3373 [模板]线段树 2 洛谷传送门 题目描述 如题,已知一个数列,你需要进行下面三种操作: 将某区间每一个数乘上 xx 将某区间每一个数加上 xx 求出某区间每一个数的和 输入格式 第一 ...

  9. 【BZOJ-4530】大融合 线段树合并

    4530: [Bjoi2014]大融合 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 280  Solved: 167[Submit][Status] ...

  10. 洛谷P4344 脑洞治疗仪 [SHOI2015] 线段树+二分答案/分块

    !!!一道巨恶心的数据结构题,做完当场爆炸:) 首先,如果你用位运算的时候不小心<<打成>>了,你就可以像我一样陷入疯狂的死循环改半个小时 然后,如果你改出来之后忘记把陷入死循 ...

随机推荐

  1. Jet --theory

    (FIG. 6. A caricature of turbulent jet and the entrainment., Jimmy, 2012) Ref: Jimmy Philip, Phys. F ...

  2. codechef营养题 第二弹

    第二弾が始まる! codechef problems 第二弹 一.Backup Functions 题面 One unavoidable problem with running a restaura ...

  3. [bzoj3209][花神的数论题] (数位dp+费马小定理)

    Description 背景众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦.描述话说花神这天又来讲课了.课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了. ...

  4. 微信小程序-template模板

    ============================= 构建template模板                    ============================= 1.分析得出共为 ...

  5. IIS部署网站只有首页能访问,其他链接失效/运行.net+Access网站-可能原因:IIS未启用32位应用程序模式

    在64位的机子上IIS运行32位的.NET程序 由于64位操作系统不支持Microsoft OLE DB Provider for Jet驱动程 也不支持更早的Microsoft Access Dri ...

  6. 初次使用Let's encrypt

    wget --no-check-certificate -O shadowsocks.sh https://raw.githubusercontent.com/teddysun/shadowsocks ...

  7. Codeforces Round #544 (Div. 3) Editorial C. Balanced Team

    http://codeforces.com/contest/1133/problem/Ctime limit per test 2 secondsmemory limit per test 256 m ...

  8. P1009 阶乘之和 洛谷

    https://www.luogu.org/problem/show?pid=1009 题目描述 用高精度计算出S=1!+2!+3!+…+n!(n≤50) 其中“!”表示阶乘,例如:5!=54321. ...

  9. I/O 模型及其设计模式

    来源:伯乐在线 - 咸菜 链接:http://blog.jobbole.com/104638/ 前言 I/O在软件开发中的重要性无需多言,无论是在操作系统.网络协议.DBMS这种底层支撑软件还是在移动 ...

  10. Android学习路线(十八)支持不同设备——支持不同的屏幕

    Android系统使用两个普通属性:尺寸和密度,来对设备屏幕进行分类. 你须要先预測你的应用将会在什么样屏幕的设备上安装,包含屏幕尺寸和密度.这种话,你就须要提供一些可选的资源类让你的应用在不同屏幕的 ...