题意及思路: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. dotNET面试(二)

    值类型与引用类型 1.值类型和引用类型的区别? 值类型包括简单类型.结构体类型和枚举类型,引用类型包括自定义类.数组.接口.委托等. 赋值方式:将一个值类型变量赋给另一个值类型变量时,将复制包含的值. ...

  2. linux随笔-03

    必须掌握的Linux命令 系统状态检测命令 1.ifconfig命令 ifconfig命令用于获取网卡配置与网络状态等信息,格式为“ifconfig [网络设备] [参数]”. 使用ifconfig命 ...

  3. NOIP2016D1T3 换教室 (概率DP)

    NOIP2016D1T3 换教室 题目大意:有n个时间段,每个时间段i有两个教室a[i],b[i]可以上课,如果不申请换教室就在教室a[i]上课,如果换教室就在b[i]上课.你最多只能换m次教室.教室 ...

  4. 五、properties编写

    1.properties和yml编写对比 2.properties中文乱码解决 上面的内容输出的结果 原因 idea 默认编码是UTF-8,properties需要修改对应的编码 设置编码后的结果正常 ...

  5. FPN在faster_rcnn中实现细节代码说明

    代码参考自:https://github.com/DetectionTeamUCAS/FPN_Tensorflow 主要分析fpn多层金字塔结构的输出如何进行预测. FPN金字塔结构插入在faster ...

  6. 最近开发的项目,遇到用户上传excel文件并导入数据到系统这个需求,而有excel中有的单元格是日期格式,本文介绍怎么从excel中读取日期格式的数据。

    可以先判断单元格的类型,有的日期是字符串存储的,有的是按日期存储的(单元格按数字解析),代码如下: Cell cell = row.getCell(); Date date = null; if (c ...

  7. 关于LCN分布式事务框架

    基于LCN框架解决分布式事务 LCN官网 https://www.txlcn.org/ "LCN并不生产事务,LCN只是本地事务的搬运工" 兼容 dubbo.springcloud ...

  8. Hibernate的优点与缺点

    Hibernate优点: 1.对象化.人员以面相对象的思想来操作数据库.Hibernate支持许多面向对象的特性,如组合,继承,多态等. 2.更好的移植性.对于不同的数据库,开发者只需要使用相同的数据 ...

  9. apue 第4章 文件和目录

    获取文件属性 #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int stat(c ...

  10. [CSP-S模拟测试]:时间机器(贪心+set)

    题目描述 作为一名天才科学家,$Kurisu$已经设计出了时间机器的构造. 根据$Kurisu$的构想,时间机器中有$n$种需要放置电阻的节点,第$i$种节点有$s_i$个,其电压$U$的变动范围是$ ...