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次询问 ...
随机推荐
- elasticsearch5.0.1集群排错的几个思路总结
1.首先查看集群整体健康状态 # curl -XGET http://10.27.35.94:9200/_cluster/health?pretty { "cluster_name" ...
- bootstrapValidator使用总结
1.根据条件动态增删检查条件 参考文章:https://blog.csdn.net/sxlzs_/article/details/78211928 #去除某字段的验证 $("#formRes ...
- UVA 11796
题意: 有两个狗, 按照 多边形跑,不知道两条狗的速度,但是狗是同时出发,同时到达终点的 输出两条狗的 最大相距距离 - 最小相距距离: 思路 : 用物理的相对运动来计算, 每次只计算 两条狗的直线 ...
- [JavaScript]使用ArrayBuffer和Blob编辑二进制流
Blob()构造方法返回一个新的Blob对象. 内容是包含参数array的二进制字节流. 语法 var aBlob = new Blob( array, options ); 参数 array is ...
- C语言-用函数实现社保工资查询系统
需求: 1.有登陆操作,超过三次需重新打开登录 2.查询五险一金.税前税后工资计算,个人与单位应缴明细 3.输入税后工资和税前工资都可查询 4.退出有询问确认操作 代码如下; #include< ...
- Hystrix浅谈
Hystrix如何使用很多说明,看了很多博客,却发现能说明一些简单概念的文章就没有. 所以本文不太回去说如何使用 Hystrix ,但是会简明的说一下 一些概念 super(Setter.withGr ...
- Tornado学习笔记(一) helloword/多进程/启动参数
前言 当你觉得你过得很舒服的时候,你肯定没有在进步.所以我想学习新的东西,然后选择了Tornado.因为我觉得Tornado更匹配目前的我的综合素质. Tornado学习笔记系列主要参考<int ...
- 28)django-form+ajax实现验证
form+ajax实现验证 #obj.errors返回的是ErrorDict,不是字典(虽然继承字典) #obj.errors.as_json() 返回的字符串(前端要连续反解两次) #obj.err ...
- OC对象本质
@interface person:NSObject{ @public int _age; } @end @implementation person @end @interface student: ...
- cf1144G 将串分解成单调递增和递减子串(贪心)
这算哪门子dp.. 具体做法就是贪心,建立两个vector存递增序列递减序列,操作过程中a可以合法地匀一个给b 就是判断第i个数放在递增序列里还是放在递减序列里,需要根据后面的数来进行决策 #incl ...