题意及思路:https://blog.csdn.net/u013534123/article/details/89010251

之前cf有一个和这个相似的题,不过那个题只有合并操作,没有删除操作,直接并查集搞一搞就行了。对于这个题,因为有删除操作,我们对操作序列建一颗线段树,记录每个操作影响的区间操作就可以了。这里的并查集不能路径压缩,要按秩合并,这样复杂度是O(logn)的。

代码:

#include <bits/stdc++.h>
#define ls (o << 1)
#define rs (o << 1 | 1)
#define INF 0x3f3f3f3f
#define db double
#define pii pair<int, int>
#define LL long long
using namespace std;
const int maxn = 300010;
const int Base = 300000;
vector<pii> tr[maxn * 4];
map<pii, int> mp;
map<pii, int>::iterator it;
LL res[maxn], cnt_x[maxn * 2], cnt_y[maxn * 2], sz[maxn * 2];
int f[maxn * 2];
LL ans;
pii a[maxn];
int get(int x) {
if(x == f[x]) return x;
return get(f[x]);
}
void add(int o, int l, int r, int ql, int qr, pii val) {
if(l >= ql &&r <= qr) {
tr[o].push_back(val);
return;
}
int mid = (l + r) >> 1;
if(ql <= mid) add(ls, l, mid, ql, qr, val);
if(qr > mid) add(rs, mid + 1, r, ql, qr, val);
}
void del(int x, int y) {
int x1 = get(x), y1 = get(y);
if(x1 != y1) return;
ans -= cnt_x[x] * cnt_y[x];
cnt_x[x] -= cnt_x[y], cnt_y[x] -= cnt_y[y];
sz[x] -= sz[y];
ans += cnt_x[x] * cnt_y[x];
ans += cnt_x[y] * cnt_y[y];
f[y] = y;
}
pii merge(int x, int y) {
int x1 = get(x), y1 = get(y);
if(x1 == y1) return make_pair(-1, -1);
if(sz[x1] < sz[y1]) swap(x1, y1);
ans -= cnt_x[x1] * cnt_y[x1];
ans -= cnt_x[y1] * cnt_y[y1];
sz[x1] += sz[y1];
cnt_x[x1] += cnt_x[y1], cnt_y[x1] += cnt_y[y1];
ans += cnt_x[x1] * cnt_y[x1];
f[y1] = x1;
return make_pair(x1, y1);
}
void dfs(int o, int l, int r) {
if(l == 12) {
l++;
l--;
}
stack<pii> s;
for (auto x : tr[o]) {
pii tmp = merge(x.first, x.second);
if(tmp.first != -1) s.push(tmp);
}
if(l == r) res[l] = ans;
else {
int mid = (l + r) >> 1;
dfs(ls, l, mid);
dfs(rs, mid + 1, r);
}
while(!s.empty()) {
del(s.top().first, s.top().second);
s.pop();
}
}
int main() {
int n, x, y;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &x, &y);
y += Base;
a[i] = make_pair(x, y);
if(mp.find(a[i]) == mp.end()) mp[a[i]] = i;
else {
add(1, 1, n, mp[a[i]], i - 1, a[i]);
mp.erase(a[i]);
}
}
for (it = mp.begin(); it != mp.end(); it++) {
add(1, 1, n, it -> second, n, it -> first);
}
for (int i = 1; i <= Base; i++) {
f[i] = i, cnt_x[i] = 1, cnt_y[i] = 0, sz[i] = 1;
}
for (int i = Base + 1; i <= Base * 2; i++) {
f[i] = i, cnt_x[i] = 0, cnt_y[i] = 1, sz[i] = 1;
}
dfs(1, 1, n);
for (int i = 1; i <= n; i++)
printf("%lld ", res[i]);
}

  

Codeforces 1140F 线段树 分治 并查集的更多相关文章

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

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

  2. bzoj4025二分图(线段树分治 并查集)

    /* 思维难度几乎没有, 就是线段树分治check二分图 判断是否为二分图可以通过维护lct看看是否链接出奇环 然后发现不用lct, 并查集维护奇偶性即可 但是复杂度明明一样哈 */ #include ...

  3. 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 ...

  4. BZOJ4025 二分图(线段树分治+并查集)

    之前学了一下线段树分治,这还是第一次写.思想其实挺好理解,即离线后把一个操作影响到的时间段拆成线段树上的区间,并标记永久化.之后一块处理,对于某个节点表示的时间段,影响到他的就是该节点一直到线段树根的 ...

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

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

  6. BZOJ 1018: [SHOI2008]堵塞的交通traffic(线段树分治+并查集)

    传送门 解题思路 可以离线,然后确定每个边的出现时间,算这个排序即可.然后就可以线段树分治了,连通性用并查集维护,因为要撤销,所以要按秩合并,时间复杂度\(O(nlog^2 n)\) 代码 #incl ...

  7. BZOJ3237 AHOI2013连通图(线段树分治+并查集)

    把查询看做是在一条时间轴上.那么每条边都有几段存在时间.于是线段树分治就好了. 然而在bzoj上t掉了,不知道是常数大了还是写挂了. 以及brk不知道是啥做数组名过不了编译. #include< ...

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

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

  9. [BZOJ4025]二分图(线段树分治,并查集)

    4025: 二分图 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2191  Solved: 800[Submit][Status][Discuss] ...

随机推荐

  1. Blueprint的实现

    Blueprint其实本身只是对view上的接口进行了注册,然后整体挂载在app上,Blueprint本身的目的就是组织多模块的平行共存,避免直接在app上注册view,其实更多的只是方便开发和代码的 ...

  2. 轻量级Spring定时任务(Spring-task)

    Spring3.0以后自主开发的定时任务工具,spring-task,可以将它比作一个轻量级的Quartz,而且使用起来很简单,除spring相关的包外不需要额外的包,而且支持注解和配置文件两种形式. ...

  3. docker 安装Filebeat

    1.查询镜像 docker search filebeat 2.拉取镜像 我此处选择的是prima/filebeat docker pull prima/filebeat 3.创建配置文件 fileb ...

  4. go语言从例子开始之Example11.range遍历

    range 迭代各种各样的数据结构.让我们来看看如何在我们已经学过的数据结构上使用 rang 吧. package main import "fmt" func main() { ...

  5. 最大公因数数gcd模板

    首先蒟蒻是在大佬的博客里学习的代码,代码风格多有相似之处,大佬博客https://www.cnblogs.com/lMonster81/p/10433902.html 最大公因数那,顾名思义就是两个数 ...

  6. shell 中| 用法

    | 运算符 管道符号,是unix一个很强大的功能,符号为一条竖线:"|".用法: command 1 | command 2 他的功能是把第一个命令command 1执行的结果作为 ...

  7. C语言——enum

    #include<stdio.h> enum Season { spring, summer=100, fall=96, winter }; typedef enum { Monday, ...

  8. MUI 自定义从底部弹出的弹出框内容

    最近做的项目都是在使用mui做手机网页,大致是下面的这种弹出效果 首先,引入 mui.css或者mui.min.css 引入 mui.min.js或者mui.js 第二步:<a href=&qu ...

  9. 开放融合 | “引擎级”深度对接!POLARDB与SuperMap联合构建首个云原生时空平台

    阿里巴巴新一代自研云数据库POLARDB与超图软件SuperMap GIS实现 “引擎级”深度对接,构建了自治.弹性.高可用的云原生时空数据管理平台联合解决方案,推出了业界首个“云原生数据库+云原生G ...

  10. Python--模块之time、random、os、hashlib

    今天开始模块. 首先补充 __init__.py       在python模块的每一个包中,都有一个__init__.py文件(这个文件定义了包的属性和方法)然后是一些模块文件和子目录,假如子目录中 ...