题目链接:洛谷

首先我们考虑没有撤回操作的情况,就是将每一行和每一列看做一个点(代表行的称为白点,代表列的称为黑点),每个点$(x,y)$看做一条边。

Extend操作实际上就是$x_1$行与$y_1,y_2$列联通,$x_2$行与$y_1$列联通时,$x_2$行也跟$y_2$列联通。

同一个联通块里的一个黑点和一个白点会产生1的贡献,所以就是连边操作+查询每个联通块的(黑点个数*白点个数)之和,可以使用并查集维护。

现在考虑撤回操作,其实就相当于每条边在$[t_1,t_2]$这段时间里“有贡献”,考虑建一个关于时间的线段树,将$[t_1,t_2]$拆分为log个区间,然后将这条边加入这log个区间对应的边集中,表示在这个区间的范围中这条边“有贡献”。

然后对这个线段树进行dfs,每次dfs到一个区间$[l,r]$的时候,将这个区间对应的边集的边加入并查集,退出的时候把影响消除。

其实对于大部分非均摊时间的数据结构都是可以很快撤回的,并查集也是这样。所以不能使用路径压缩,要使用按秩合并。

时间复杂度$O(n\log^2n)$

  1. #include<bits/stdc++.h>
  2. #define Rint register int
  3. #define fi first
  4. #define se second
  5. #define mp make_pair
  6. using namespace std;
  7. typedef long long LL;
  8. typedef pair<int, int> pii;
  9. const int N = ;
  10. int q, fa[N], siz[N][], top;
  11. map<pii, int> ma;
  12. vector<pii> vec[N << ];
  13. LL ans, ansx[N];
  14. inline int getfa(int x){
  15. return x == fa[x] ? x : getfa(fa[x]);
  16. }
  17. pii que[N];
  18. inline void comb(int x, int y){
  19. x = getfa(x); y = getfa(y);
  20. if(x == y) return;
  21. if(siz[x][] + siz[x][] < siz[y][] + siz[y][]) swap(x, y);
  22. ans += (LL) siz[x][] * siz[y][] + (LL) siz[x][] * siz[y][];
  23. siz[x][] += siz[y][];
  24. siz[x][] += siz[y][];
  25. fa[y] = x;
  26. que[++ top] = mp(x, y);
  27. }
  28. inline void undo(int x, int y){
  29. fa[y] = y;
  30. siz[x][] -= siz[y][];
  31. siz[x][] -= siz[y][];
  32. ans -= (LL) siz[x][] * siz[y][] + (LL) siz[x][] * siz[y][];
  33. }
  34. inline void update(int x, int L, int R, int l, int r, pii val){
  35. if(l <= L && R <= r){
  36. vec[x].push_back(val);
  37. return;
  38. }
  39. int mid = L + R >> ;
  40. if(l <= mid) update(x << , L, mid, l, r, val);
  41. if(mid < r) update(x << | , mid + , R, l, r, val);
  42. }
  43. inline void dfs(int x, int L, int R){
  44. int now = top;
  45. for(pii tmp : vec[x])
  46. comb(tmp.fi, tmp.se);
  47. if(L == R) ansx[L] = ans;
  48. else {
  49. int mid = L + R >> ;
  50. dfs(x << , L, mid); dfs(x << | , mid + , R);
  51. }
  52. while(top > now){
  53. undo(que[top].fi, que[top].se); -- top;
  54. }
  55. }
  56. int main(){
  57. scanf("%d", &q);
  58. for(Rint i = ;i <= q;i ++){
  59. int x, y;
  60. scanf("%d%d", &x, &y); y += 3e5;
  61. if(!ma.count(mp(x, y))) ma[mp(x, y)] = i;
  62. else {
  63. update(, , q, ma[mp(x, y)], i - , mp(x, y));
  64. ma.erase(mp(x, y));
  65. }
  66. }
  67. for(auto it = ma.begin();it != ma.end();it ++)
  68. update(, , q, it -> se, q, it -> fi);
  69. for(Rint i = ;i <= 3e5;i ++) fa[i] = i, siz[i][] = ;
  70. for(Rint i = 3e5 + ;i <= 6e5;i ++) fa[i] = i, siz[i][] = ;
  71. dfs(, , q);
  72. for(Rint i = ;i <= q;i ++) printf("%lld\n", ansx[i]);
  73. }

CF1140F

CF1140F Extending Set of Points 【按时间分治,并查集】的更多相关文章

  1. Codeforces 1140F Extending Set of Points (线段树分治+并查集)

    这题有以下几个步骤 1.离线处理出每个点的作用范围 2.根据线段树得出作用范围 3.根据分治把每个范围内的点记录和处理 #include<bits/stdc++.h> using name ...

  2. 【CF576E】Painting Edges 线段树按时间分治+并查集

    [CF576E]Painting Edges 题意:给你一张n个点,m条边的无向图,每条边是k种颜色中的一种,满足所有颜色相同的边内部形成一个二分图.有q个询问,每次询问给出a,b代表将编号为a的边染 ...

  3. BZOJ_4025_二分图_线段树按时间分治+并查集

    BZOJ_4025_二分图_线段树按时间分治+并查集 Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简 ...

  4. 2018.09.30 bzoj4025: 二分图(线段树分治+并查集)

    传送门 线段树分治好题. 这道题实际上有很多不同的做法: cdq分治. lct. - 而我学习了dzyo的线段树分治+并查集写法. 所谓线段树分治就是先把操作分成lognlognlogn个连续不相交的 ...

  5. CF1140F - Extending Set of Points

    题意:对于点集S,定义函数F(S)为对S不断扩展到不能扩展时S的点数.一次扩展定义为如果有一个平行于坐标轴的矩形的三个点在S中,则第四个点加入S. 动态在S中加点删点,每次操作完后求F(S)的值. 解 ...

  6. BZOJ 4025: 二分图 [线段树CDQ分治 并查集]

    4025: 二分图 题意:加入边,删除边,查询当前图是否为二分图 本来想练lct,然后发现了线段树分治的做法,感觉好厉害. lct做法的核心就是维护删除时间的最大生成树 首先口胡一个分块做法,和hno ...

  7. BZOJ3237:[AHOI2013]连通图(线段树分治,并查集)

    Description 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 Connec ...

  8. 【CF603E】Pastoral Oddities cdq分治+并查集

    [CF603E]Pastoral Oddities 题意:有n个点,依次加入m条边权为$l_i$的无向边,每次加入后询问:当前图是否存在一个生成子图,满足所有点的度数都是奇数.如果有,输出这个生成子图 ...

  9. Bzoj1018/洛谷P4246 [SHOI2008]堵塞的交通(线段树分治+并查集)

    题面 Bzoj 洛谷 题解 考虑用并查集维护图的连通性,接着用线段树分治对每个修改进行分治. 具体来说,就是用一个时间轴表示图的状态,用线段树维护,对于一条边,我们判断如果他的存在时间正好在这个区间内 ...

随机推荐

  1. 01 HTTP协议_servlet基础

    一.定义 http(Hyper Text Transfer Protocol):超文本传输协议 二.作用 数据传输 三.概念 HTTP消息: 1.客户端发向服务器的请求消息 2.服务器回给客户端的响应 ...

  2. DP动态规划学习笔记——高级篇上

    说了要肝的怎么能咕咕咕呢? 不了解DP或者想从基础开始学习DP的请移步上一篇博客:DP动态规划学习笔记 这一篇博客我们将分为上中下三篇(这样就不用咕咕咕了...),上篇是较难一些树形DP,中篇则是数位 ...

  3. Java框架 高并发系列 1第1天:必须知道的几个概念

    https://mp.weixin.qq.com/s?__biz=MzA5MTkxMDQ4MQ==&mid=2648933019&idx=1&sn=3455877c451de9 ...

  4. [书籍翻译] 《JavaScript并发编程》第三章 使用Promises实现同步

    本文是我翻译<JavaScript Concurrency>书籍的第三章 使用Promises实现同步,该书主要以Promises.Generator.Web workers等技术来讲解J ...

  5. 第三章、drf-ModelSerializer

    目录 ModelSerializer ModelSerializer 序列化 使用: ModelSerializer 反序列化 使用: ModelSerializer 序列化反序列化整合(*****) ...

  6. CPU性能的主要指标

    来源: http://blog.itpub.net/24435147/viewspace-694470/ CPU的主要指标: CPU Utilization CPU 使用率,CPU的使用时间百分比,7 ...

  7. Spring Boot 实现热部署

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring- ...

  8. 你应该使用Python3里的这些新特性

    概述 由于Python2的官方维护期即将结束,越来越多的Python项目从Python2切换到了Python3.可是,在实际的工作中,我发现好多人都是在用Python2的思维去写Python3的代码, ...

  9. LINQ图解教程

    LINQ 什么是LINQLINQ提供程序 匿名类型 方法语法和查询语法查询变量查询表达式的结构 from子句join子句什么是联结查询主体中的from…let…where片段 from子句let子句w ...

  10. file控件选择同一文件不触发change事件和img控件不改变src的情况下图片不刷新问题解决

    最近跑来前端掺和了.. file控件的问题用 inputFile.value = ''; img控件的问题,在图片后面添加一串无意义的参数即可,例如: img.src = 'file:///' + 本 ...