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 线段树 + 按秩合并并查集 (看题解)的更多相关文章

  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. BZOJ.3673/3674.可持久化并查集(可持久化线段树 按秩合并/启发式合并)

    BZOJ 3673 BZOJ 3674(加强版) 如果每次操作最多只修改一个点的fa[],那么我们可以借助可持久化线段树来O(logn)做到.如果不考虑找fa[]的过程,时空复杂度都是O(logn). ...

  5. CF1140F Extending Set of Points 【按时间分治,并查集】

    题目链接:洛谷 首先我们考虑没有撤回操作的情况,就是将每一行和每一列看做一个点(代表行的称为白点,代表列的称为黑点),每个点$(x,y)$看做一条边. Extend操作实际上就是$x_1$行与$y_1 ...

  6. 线段树区间离散化维护按秩合并并查集(可撤销)——牛客多校第八场E

    模板题..去网上学了可撤销的并查集.. /* 给定一个无向图,边的属性为(u,v,l,r),表示<u,v>可以通过的size为[l,r] 求出有多少不同的size可以从1->n 把每 ...

  7. [Codeforces 266E]More Queries to Array...(线段树+二项式定理)

    [Codeforces 266E]More Queries to Array...(线段树+二项式定理) 题面 维护一个长度为\(n\)的序列\(a\),\(m\)个操作 区间赋值为\(x\) 查询\ ...

  8. [Codeforces 280D]k-Maximum Subsequence Sum(线段树)

    [Codeforces 280D]k-Maximum Subsequence Sum(线段树) 题面 给出一个序列,序列里面的数有正有负,有两种操作 1.单点修改 2.区间查询,在区间中选出至多k个不 ...

  9. codeforces 1217E E. Sum Queries? (线段树

    codeforces 1217E E. Sum Queries? (线段树 传送门:https://codeforces.com/contest/1217/problem/E 题意: n个数,m次询问 ...

随机推荐

  1. JQery插件zClip ----实现粘贴复制功能

    使用了这个插件,但是用在table,td中话,我是一个列表来的,对此使用此插件还是有点问题的?点击其中的一个会全部都被选中. <script type="text/javascript ...

  2. 用puttygen工具把私钥id_rsa转换成公钥id_rsa.ppk

    1 前言 有时候需要ppk格式的公钥,可以用putty来处理 2 步骤 1. 产生密钥 可以参考Gitlab的SSH配置(linux和windows双版本) $ ssh-keygen -t rsa - ...

  3. ubuntu安装pycharm并建立桌面快捷方式

    环境:ubuntu18.04 参考文章:本地安装:https://blog.csdn.net/liuxiao214/article/details/78893457 在线安装:https://www. ...

  4. MYSQL修改字段

    当字段为空则插入0,不为空则原来的值  UPDATE t_pm_scheduleSET lesson_room_id1 = IFNULL(lesson_room_id1, 0), lesson_roo ...

  5. TIMESTAMPDIFF用法

    TIMESTAMPDIFF用法: TIMESTAMPDIFF(interval,datetime_expr1,datetime_expr2) 返回日期或日期时间表达式datetime_expr1 和d ...

  6. iOS Code Sign On Copy

    上面的图中,code sign on copy 是什么意思呢? 先看专业的解释:http://stackoverflow.com/questions/30963294/creating-ios-osx ...

  7. Python基础-入门之路PYTHON-包 相对导入&绝对导入

    什么是包 包也是一种模块,但本质上就是一个文件夹 对于使用者而言 使用方式和模块没有任何区别 本质上就是一个文件夹 不同之处在于 多了一个__init__.py 叫包的初始化文件 import导入模块 ...

  8. AMD-requireJS

    require.js是AMD的一种实现形式. 加载: <script src="require.js" data-main="main"></ ...

  9. C# 通用数据库配置界面,微软原生DLL重整合

    C# 通用数据库配置界面,微软原生DLL重整合 自己整合了 微软自带的数据连接配置界面对话库    Microsoft.Data.ConnectionUI.Dialog.dll  微软自带的数据连接配 ...

  10. linux 使用的部分命令

    搜索所有运行着的线程 ps -A | grep apt-get 你会得到类似下面的输出: root ? Ss : : /bin/sh /usr/lib/apt/apt.systemd.daily _a ...