题干:

小T有n个点,每个点可能是黑色的,可能是白色的。
小T对这张图的定义了白连通块和黑连通块:
白连通块:图中一个点集V,若满足所有点都是白点,并且V中任意两点都可以只经过V中的点互相到达,则称V中的点构成了一个白连通块。

黑连通块:类似白连通块的定义。

小T对这n个点m次操作。
1、在两个点之间连一条边。
2、询问白(黑)连通块个数。
3、给出x,y两个点,保证同色(为了方便描述,x,y都是白点,黑色同理)。询问存在多少个黑点,将它改变颜色后,x,y所在的白连通块会合并为一个。如果x,y已经在一个白连通块内了,输出-1。(注意:这里不会对点的颜色改变,只统计个数)

输入描述:

第一行两个整数n,m,分别表示点的个数和操作的个数。
第二行n个整数,第i个整数描述第i个点的颜色,0表示白色,1表示黑色。
接下来m行,每行包含2个或者3个整数,描述三种操作。
操作1:1,x,y,表示在x,y之间加入一条边。
操作2:2,x,若x=0,询问白连通块的个数,否则询问黑连通块的个数。
操作3:3,x,y,表示第三种操作。
n,m≤50000,x,y≤nn,m≤50000,x,y≤n

输出描述:

对于询问操作,输出一个整数。

示例1

输入

复制

6 7
0 1 0 0 0 1
1 3 2
1 2 4
3 3 4
1 1 3
2 0
3 1 4
3 1 3

输出

复制

1
3
1
-1

说明

第一次询问:2号点变成白色后,3,4所在的白连通块合并为一个。
第二次询问:白连通块的个数为3,分别是{1,2},{3},{4}。
第三次询问:2号点变成白色后,1,4所在的白连通块合并为一个。
第四次询问:1,3已经是同一个白连通块了,输出-1。

解题报告:

并查集+bitset优化。
操作二可以在加边的过程中求出。即加入一条端点同色的边,并查集判断是否可以消去一个白(黑)连通块。
操作三求的是x,y所在的两个白连通块都连出的黑点(假设x,y是白色,黑色的情况是一样的)。
于是可以bitset维护每个白联通块连出的黑点,黑连通块连出的白点。每加入一条端点异色的边,在两个白、黑连通块的bitset中将一个位置设为1;加入一条端点同色的边,就是合并白(黑)连通块的过程,同时合并两个白(黑)连通块的bitset。
复杂度,W=32或64

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<bitset>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 6e4 + 5;
int col[MAX];
int f[MAX];
int totbai,tothei,bai,hei;
bitset<MAX> bs[MAX];
int getf(int v) {return v == f[v] ? v : f[v] = getf(f[v]);
}
void add(int u,int v) {int t1 = getf(u);int t2 = getf(v);if(col[u] == col[v]) {if(t1 != t2) {if(col[u] == 0) bai--;else hei--; }f[t2] = t1;bs[t1] |= bs[t2];//这两句也可以放在if里 }else {bs[t1].set(v);//bs[t1][v]=1;bs[t2].set(u);//bs[t2][u]=1;}
}
int main()
{int n,m;cin>>n>>m;for(int i = 1; i<=n; i++) {scanf("%d",col+i);f[i] = i;}for(int i = 1; i<=n; i++) {if(col[i] == 1) hei++,tothei++;else bai++,totbai++;}for(int op,x,y,i = 1; i<=m; i++) {scanf("%d",&op);if(op == 1) {scanf("%d%d",&x,&y);add(x,y);}else if(op == 2) {scanf("%d",&x);printf("%d\n",x == 1 ? hei : bai);}else {scanf("%d%d",&x,&y);int t1 = getf(x);int t2 = getf(y);if(t1 == t2) puts("-1");else {printf("%d\n",(bs[t1]&bs[t2]).count());}}}return 0 ;}

其实merge函数这样写比较清晰:

void merge(int u,int v) {int t1 = getf(u),t2 = getf(v);if(t1 == t2) return;if(col[t1] == col[t2]) {        if(col[t1] == 1) hei--;else bai--;f[t2]=t1;bs[t1] |= bs[t2];}else bs[t1][v]=bs[t2][u]=1;
}

简化版:

const int N=5e4+5;
int n,m,col[N],fa[N],num[2];bitset<N>S[N];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
int main(){n=gi();m=gi();for(int i=1;i<=n;++i)++num[col[i]=gi()],fa[i]=i;while(m--){int op=gi(),x=gi(),y;if(op&1)y=gi();if(op==1)if(col[x]^col[y])S[find(x)][y]=1,S[find(y)][x]=1;else{x=find(x),y=find(y);if(x^y)fa[y]=x,S[x]|=S[y],--num[col[x]];}if(op==2)printf("%d\n",x?num[1]:num[0]);if(op==3)printf("%d\n",find(x)^find(y)?(int)(S[find(x)]&S[find(y)]).count():-1);}return 0;
}

总结:

这个tothei和totbai,计算过程中始终没有用到,但是作为一个流程性的东西,万一给你改变一下题目,说不定就用到了,所以提前维护出来为好。

【牛客 - 368D】动态连通块(并查集+bitset优化)相关推荐

  1. AcWing4084 号码牌 (并查集 / bitset优化Floyd)

    题目链接: 号码牌 大致题意 给定一个长度为nnn的序列, 第iii个位置的值为aia_iai​. (保证aaa是111~nnn的一个排列) 每个位置还有一个值did_idi​, 若满足∣i−j=di ...

  2. 2021牛客暑期多校训练营8 F-Robots(bitset优化dp)

    F-Robots 第一种第二种机器人直接O(n)O(n)O(n)判断即可. 第三种机器人暴力dp,用bitset优化. bitset<250005> b[i][j] 表示从(i,j)(i, ...

  3. 牛客 - 牛半仙的妹子图(并查集+bitset/克鲁斯卡尔重构树+主席树)

    题目链接:点击查看 题目大意:给出一个由 n 个点和 m 条边组成的连通图,每个点都有一种颜色,每条边都有一个权值,现在规定一个起点 st,再给出 q 次询问,每次询问给出区间 [ l , r ] , ...

  4. 牛客小白月赛12 J 月月查华华的手机 (序列自动机模板题)

    链接:https://ac.nowcoder.com/acm/contest/392/J 来源:牛客网 题目描述 月月和华华一起去吃饭了.期间华华有事出去了一会儿,没有带手机.月月出于人类最单纯的好奇 ...

  5. 牛客网java专项练习错题集--1

     1.有关hashMap跟hashTable的区别,说法正确的是?(ABCD) A HashMap和Hashtable都实现了Map接口 B HashMap是非synchronized,而Hashta ...

  6. 树上动态插点 ---- F. Imbalance Value of a Tree(树上动态插点 + 并查集)

    题目链接 题目大意: 定义I(x,y)为x到y路径上最大值和最小值之差I(x,y)为x到y路径上最大值和最小值之差I(x,y)为x到y路径上最大值和最小值之差 现在叫你求∑i=1n∑j=inI(x,y ...

  7. 牛客第二场 G.League of Legends-单调队列优化dp

    https://ac.nowcoder.com/acm/contest/11253/G 上面出题人给的题解: 思路基本差不多,这里主要说一下合并小区间的dp, dp[i][j]代表前i个分成j组最大的 ...

  8. 《牛客刷题》sql错题集

    1. 查询语句select stuff('lo ina',3, 1, 've ch')结果为? 答案:love china 解析: STUFF(原字符, 开始位置, 删除长度, 插入字符) 从指定的起 ...

  9. 牛客练习赛75 E.炒鸡矿工(dp的优化)

    传送门 T1T1T1 定义f[i][j][q]f[i][j][q]f[i][j][q]表示第iii分钟等级为jjj,距离下次收矿还剩qqq分钟的最大收益 枚举iii,枚举jjj,枚举qqq,复杂度达到 ...

最新文章

  1. HTML封装AJAX请求,在请求里面写登录的逻辑 ajax 网络请求 post
  2. 一些或许用的到的小Demo
  3. 面对众多的前端框架,你该如何学习?
  4. LeetCode OJ - Surrounded Regions
  5. Python类、模块、包的区别
  6. java输入、输出流的简单入门
  7. 米家app扫描不到石头机器人_12月米家剁手清单,第二款冬天必备!
  8. 汉医健康:“互联网+医疗健康”让患者更有“医”靠
  9. efi启动修复linux引导文件夹,一次修复linux的efi引导的集中方法总结记录
  10. 如何修改游戏服务器ip地址吗,怎么修改游戏服务器ip地址
  11. 浙江省 教师资格证 岗前培训考试 浙江高培中心报名系统
  12. 去除chrome自动填充黄底样式
  13. 《MS17-010(永恒之蓝)—漏洞复现及防范》
  14. 惠普win10一键还原_惠普win10一键还原,惠普电脑怎么进入bios
  15. 读《信任代理》的点滴札记
  16. 海外新闻稿发布平台TOP10,媒介易为你盘点热门选择!
  17. 特斯拉的12V蓄电池有什么不同?
  18. 用Python做一个奥特曼打怪兽的小游戏
  19. 二维码生成器和二维码扫描器
  20. docker_容器间的链接 link

热门文章

  1. [剑指offer]面试题第[7]题[JAVA][斐波那契数列][递归]
  2. POJ-1845 数论
  3. python实验九答案_Python实验九
  4. svn不知道这样的主机 怎么解决_家里装修不知道怎么配置净水器,这几招教你轻松解决...
  5. 撤销 恢复快捷键 Linux,Linux Vim撤销和恢复撤销快捷键用法详解
  6. java I O类大全_Java I/O最简单的几个类
  7. php中的解析范围符,如何合理使用php7范围解析操作符
  8. 2019数据安装勾选_【安装部署】esweb服务器如何单独部署
  9. Tecplot云图锯齿状边界解决办法
  10. apache根据ip分发_腾讯广告进入“IP新融点”时代