Codeforces 1140F Extending Set of Points 线段树 + 按秩合并并查集 (看题解)
我们能发现, 如果把x轴y轴看成点, 那么答案就是在各个连通块里面的x轴的个数乘以y轴的个数之和。
然后就变成了一个并查集的问题, 但是这个题目里面有撤销的操作, 所以我们要把加入和撤销操作变成
这个点影响(L , R)之间的询问, 然后把它丢到线段树里面分成log段, 然后我们dfs一遍线段树, 用按秩合并
并查集取维护, 回溯的时候将并查集撤销。
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long using namespace std; const int N = 3e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = ;
const double eps = 1e-;
const double PI = acos(-); int n;
LL ans[N];
map<PII, int> Map; int fa[N << ], cntx[N << ], cnty[N << ], sz[N << ];
LL now = ; #define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
vector<PII> vc[N << ];
void Insert(int L, int R, PII e, int l, int r, int rt) {
if(l >= L && r <= R) {
vc[rt].push_back(e);
return;
}
int mid = l + r >> ;
if(L <= mid) Insert(L, R, e, lson);
if(R > mid) Insert(L, R, e, rson);
} int getRoot(int x) {
return fa[x] == x ? x : getRoot(fa[x]);
} void Merge(int x, int y, stack<PII>& stk) {
int fax = getRoot(x);
int fay = getRoot(y);
if(fax != fay) {
if(sz[fax] < sz[fay]) swap(fax, fay);
stk.push(mk(fax, fay));
now -= 1ll * cntx[fax] * cnty[fax];
now -= 1ll * cntx[fay] * cnty[fay];
sz[fax] += sz[fay];
cntx[fax] += cntx[fay];
cnty[fax] += cnty[fay];
fa[fay] = fax;
now += 1ll * cntx[fax] * cnty[fax];
}
} void Delete(stack<PII>& stk) {
while(!stk.empty()) {
int fax = stk.top().fi;
int fay = stk.top().se;
stk.pop();
now -= 1ll * cntx[fax] * cnty[fax];
sz[fax] -= sz[fay];
cntx[fax] -= cntx[fay];
cnty[fax] -= cnty[fay];
fa[fay] = fay;
now += 1ll * cntx[fax] * cnty[fax];
now += 1ll * cntx[fay] * cnty[fay];
}
} void dfs(int l, int r, int rt) {
stack<PII> stk;
for(auto& t : vc[rt]) Merge(t.fi, t.se, stk);
if(l == r) ans[l] = now;
else {
int mid = l + r >> ;
dfs(l, mid, rt << );
dfs(mid + , r, rt << | );
}
Delete(stk);
} int main() {
scanf("%d", &n);
for(int i = ; i <= n; i++) {
PII e; scanf("%d%d", &e.fi, &e.se);
e.se += ;
if(Map.find(e) == Map.end()) {
Map[e] = i;
} else {
Insert(Map[e], i - , e, , n, );
Map.erase(e);
}
}
for(auto& t : Map) Insert(t.se, n, t.fi, , n, );
for(int i = ; i <= ; i++) fa[i] = i, cntx[i] = , sz[i] = ;
for(int i = ; i <= ; i++) fa[i] = i, cnty[i] = , sz[i] = ;
dfs(, n, );
for(int i = ; i <= n; i++) printf("%lld ", ans[i]);
puts("");
return ;
} /*
*/
Codeforces 1140F Extending Set of Points 线段树 + 按秩合并并查集 (看题解)的更多相关文章
- Codeforces 1140F Extending Set of Points (线段树分治+并查集)
这题有以下几个步骤 1.离线处理出每个点的作用范围 2.根据线段树得出作用范围 3.根据分治把每个范围内的点记录和处理 #include<bits/stdc++.h> using name ...
- 【CF576E】Painting Edges 线段树按时间分治+并查集
[CF576E]Painting Edges 题意:给你一张n个点,m条边的无向图,每条边是k种颜色中的一种,满足所有颜色相同的边内部形成一个二分图.有q个询问,每次询问给出a,b代表将编号为a的边染 ...
- BZOJ_4025_二分图_线段树按时间分治+并查集
BZOJ_4025_二分图_线段树按时间分治+并查集 Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简 ...
- BZOJ.3673/3674.可持久化并查集(可持久化线段树 按秩合并/启发式合并)
BZOJ 3673 BZOJ 3674(加强版) 如果每次操作最多只修改一个点的fa[],那么我们可以借助可持久化线段树来O(logn)做到.如果不考虑找fa[]的过程,时空复杂度都是O(logn). ...
- CF1140F Extending Set of Points 【按时间分治,并查集】
题目链接:洛谷 首先我们考虑没有撤回操作的情况,就是将每一行和每一列看做一个点(代表行的称为白点,代表列的称为黑点),每个点$(x,y)$看做一条边. Extend操作实际上就是$x_1$行与$y_1 ...
- 线段树区间离散化维护按秩合并并查集(可撤销)——牛客多校第八场E
模板题..去网上学了可撤销的并查集.. /* 给定一个无向图,边的属性为(u,v,l,r),表示<u,v>可以通过的size为[l,r] 求出有多少不同的size可以从1->n 把每 ...
- [Codeforces 266E]More Queries to Array...(线段树+二项式定理)
[Codeforces 266E]More Queries to Array...(线段树+二项式定理) 题面 维护一个长度为\(n\)的序列\(a\),\(m\)个操作 区间赋值为\(x\) 查询\ ...
- [Codeforces 280D]k-Maximum Subsequence Sum(线段树)
[Codeforces 280D]k-Maximum Subsequence Sum(线段树) 题面 给出一个序列,序列里面的数有正有负,有两种操作 1.单点修改 2.区间查询,在区间中选出至多k个不 ...
- codeforces 1217E E. Sum Queries? (线段树
codeforces 1217E E. Sum Queries? (线段树 传送门:https://codeforces.com/contest/1217/problem/E 题意: n个数,m次询问 ...
随机推荐
- JQery插件zClip ----实现粘贴复制功能
使用了这个插件,但是用在table,td中话,我是一个列表来的,对此使用此插件还是有点问题的?点击其中的一个会全部都被选中. <script type="text/javascript ...
- 用puttygen工具把私钥id_rsa转换成公钥id_rsa.ppk
1 前言 有时候需要ppk格式的公钥,可以用putty来处理 2 步骤 1. 产生密钥 可以参考Gitlab的SSH配置(linux和windows双版本) $ ssh-keygen -t rsa - ...
- ubuntu安装pycharm并建立桌面快捷方式
环境:ubuntu18.04 参考文章:本地安装:https://blog.csdn.net/liuxiao214/article/details/78893457 在线安装:https://www. ...
- MYSQL修改字段
当字段为空则插入0,不为空则原来的值 UPDATE t_pm_scheduleSET lesson_room_id1 = IFNULL(lesson_room_id1, 0), lesson_roo ...
- TIMESTAMPDIFF用法
TIMESTAMPDIFF用法: TIMESTAMPDIFF(interval,datetime_expr1,datetime_expr2) 返回日期或日期时间表达式datetime_expr1 和d ...
- iOS Code Sign On Copy
上面的图中,code sign on copy 是什么意思呢? 先看专业的解释:http://stackoverflow.com/questions/30963294/creating-ios-osx ...
- Python基础-入门之路PYTHON-包 相对导入&绝对导入
什么是包 包也是一种模块,但本质上就是一个文件夹 对于使用者而言 使用方式和模块没有任何区别 本质上就是一个文件夹 不同之处在于 多了一个__init__.py 叫包的初始化文件 import导入模块 ...
- AMD-requireJS
require.js是AMD的一种实现形式. 加载: <script src="require.js" data-main="main"></ ...
- C# 通用数据库配置界面,微软原生DLL重整合
C# 通用数据库配置界面,微软原生DLL重整合 自己整合了 微软自带的数据连接配置界面对话库 Microsoft.Data.ConnectionUI.Dialog.dll 微软自带的数据连接配 ...
- linux 使用的部分命令
搜索所有运行着的线程 ps -A | grep apt-get 你会得到类似下面的输出: root ? Ss : : /bin/sh /usr/lib/apt/apt.systemd.daily _a ...