https://ac.nowcoder.com/acm/contest/368/D

题意

小T有n个点,每个点可能是黑色的,可能是白色的。
小T对这张图的定义了白连通块和黑连通块:
白连通块:图中一个点集V,若满足所有点都是白点,并且V中任意两点都可以只经过V中的点互相到达,则称V中的点构成了一个白连通块。
黑连通块:类似白连通块的定义。
小T对这n个点m次操作。
1、在两个点之间连一条边。
2、询问白(黑)连通块个数。
3、给出x,y两个点,保证同色(为了方便描述,x,y都是白点,黑色同理)。询问存在多少个黑点,将它改变颜色后,x,y所在的白连通块会合并为一个。如果x,y已经在一个白连通块内了,输出-1。(注意:这里不会对点的颜色改变,只统计个数)

思路

感觉这个并查集还是很妙的,颜色相同的想要合并就按照正常的并查集来。如果颜色不同,直接合并没有意义,用bitset记录下来,两个白点如果bitset中有相同的黑点,那么这个点就是第三问中的一个合法点。

#include <algorithm>
#include <iterator>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <stack>
#include <cmath>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <cassert> /* ⊂_ヽ
  \\ Λ_Λ 来了老弟
   \('ㅅ')
    > ⌒ヽ
   /   へ\
   /  / \\
   レ ノ   ヽ_つ
  / /
  / /|
 ( (ヽ
 | |、\
 | 丿 \ ⌒)
 | |  ) /
'ノ )  Lノ */ using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3; //priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '\n' #define boost ios::sync_with_stdio(false);cin.tie(0)
#define rep(a, b, c) for(int a = (b); a <= (c); ++ a)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c); const ll oo = 1ll<<;
const ll mos = 0x7FFFFFFF; //
const ll nmos = 0x80000000; //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //
const int mod = 1e9+;
const double esp = 1e-;
const double PI=acos(-1.0);
const double PHI=0.61803399; //黄金分割点
const double tPHI=0.38196601; template<typename T>
inline T read(T&x){
x=;int f=;char ch=getchar();
while (ch<''||ch>'') f|=(ch=='-'),ch=getchar();
while (ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
return x=f?-x:x;
} inline void cmax(int &x,int y){if(x<y)x=y;}
inline void cmax(ll &x,ll y){if(x<y)x=y;}
inline void cmin(int &x,int y){if(x>y)x=y;}
inline void cmin(ll &x,ll y){if(x>y)x=y;} /*-----------------------showtime----------------------*/ const int maxn = 5e4+;
int col[maxn],fa[maxn];
bitset<> b[maxn],tmp;
int ans[];
int find(int x){
if(fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
void uni(int x,int y){
int fx = find(x), fy = find(y);
if(col[x] == col[y]){
if(fx != fy){
fa[fx] = fy;
ans[col[x]]--;
b[fy] |= b[fx];
}
}
else b[fx].set(y), b[fy].set(x);
} void cal(int x,int y){
int fx = find(x), fy = find(y);
if(fx == fy) puts("-1");
else {
tmp = b[fx] & b[fy];
printf("%d\n", (int)tmp.count());
}
}
int main(){
int n,m;
scanf("%d%d", &n, &m);
rep(i, , n) scanf("%d", &col[i]), fa[i] = i, ans[col[i]] ++;
while(m--){
int op; scanf("%d", &op);
if(op == ) {
int x, y; scanf("%d%d", &x, &y);
uni(x, y);
}
else if(op == ) {
int x; scanf("%d", &x);
printf("%d\n", ans[x]);
}
else {
int x,y; scanf("%d%d", &x, &y);
cal(x, y);
}
}
return ;
}

牛客练习赛39 D 动态连通块+并查集 X bitset 优化的更多相关文章

  1. 牛客练习赛16 C 任意点【并查集/DFS/建图模型】

    链接:https://www.nowcoder.com/acm/contest/84/C 来源:牛客网 题目描述 平面上有若干个点,从每个点出发,你可以往东南西北任意方向走,直到碰到另一个点,然后才可 ...

  2. 牛客练习赛39 B.选点

    链接:https://ac.nowcoder.com/acm/contest/368/B 来源:牛客网 题目描述 有一棵n个节点的二叉树,1为根节点,每个节点有一个值wi.现在要选出尽量多的点. 对于 ...

  3. 牛客练习赛39 B:选点(二叉树遍历+LIS)

    链接: https://ac.nowcoder.com/acm/contest/368/B 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言262 ...

  4. PAT天梯赛练习题——L3-004. 肿瘤诊断(三维连通块并查集)

    L3-004. 肿瘤诊断 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 在诊断肿瘤疾病时,计算肿瘤体积是很重要的一环.给定病灶 ...

  5. LightOJ——1012Guilty Prince(连通块并查集)

    1012 - Guilty Prince Time Limit: 2 second(s) Memory Limit: 32 MB Once there was a king named Akbar. ...

  6. 牛客小白月赛28 J.树上行走 (并查集,dfs)

    题意:有\(n\)个点,\(n-1\)条边,每个点的类型是\(0\)或\(1\),现在让你选一个点,然后所有与该点类型不同的点直接消失,问选哪些点之后,该点所在的联通块最大. 题解: 因为选完之后两个 ...

  7. 牛客网-Beauty of Trees 【加权并查集】

    锟斤拷锟接o拷https://www.nowcoder.com/acm/contest/119/A锟斤拷源锟斤拷牛锟斤拷锟斤拷 锟斤拷目锟斤拷锟斤拷 It锟斤拷s universally acknow ...

  8. UVA 572 油田连通块-并查集解决

    题意:8个方向如果能够连成一块就算是一个连通块,求一共有几个连通块. 分析:网上的题解一般都是dfs,但是今天发现并查集也可以解决,为了方便我自己理解大神的模板,便尝试解这道题目,没想到过了... # ...

  9. 牛客练习赛39 C 流星雨 (概率dp)

    题意: 现在一共有n天,第i天如果有流星雨的话,会有wi颗流星雨. 第1天有流星雨的概率是p1. 如果第i−1 (i≥2)天有流星雨,第i天有流星雨的可能性是pi+P,否则是pi. 求n天后,流星雨颗 ...

随机推荐

  1. RobotFramework_1.简介和安装

    RobotFramework_1.简介与安装 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bot ...

  2. HomeBrew 安装

    HomeBrew中文地址 通过以上链接把安装地址拿到, 这个地址可能会变, 再次使用需要重新获取: /usr/bin/ruby -e "$(curl -fsSL https://raw.gi ...

  3. Angular JS 中的内置方法之$watch

    在$apply方法中存在脏检查,首先apply方法会触发evel方法,当evel方法解析成功后,会去触发digest方法,digest方法会触发watch方法. $watch(watchFn,watc ...

  4. http状态码 400-499

    类比 服务器:便利店 客户端:客人 http报文:中文语言+钱 400-499 客户的错误 400 :服务器不理解客服端请求的意思是什么,如请求报文损坏 举例: 客户端:@#!3&* 服务器: ...

  5. Unity通过NTP获取网络时间

    最初通过qq时间服务器获得时间,经常出现有网络也获取失败的情况. 后面寻找解决办法,查找资料终于发现通过ntp时间服务器获取网络时间的方法.   首先游戏开始获得初始化网络时间,通常只获取一次,其他时 ...

  6. SonarQube系列一、Linux安装与部署

    [前言] 随着项目团队规模日益壮大,项目代码量也越来越多.且不说团队成员编码水平层次不齐,即便是老手,也难免因为代码量的增加和任务的繁重而忽略代码的质量,最终的问题便是bug的增多和代码债务的堆积.因 ...

  7. 一文了解:Redis的AOF持久化

    Redis的AOF持久化 每当Redis-Server接收到写数据时,就把命令以文本形式追加到AOF文件里,当重启Redis服务时,AOF文件里的命令会被重新执行一次,重新恢复数据.当AOF过大时将重 ...

  8. JWT+Interceptor实现无状态登录和鉴权

    无状态登录原理 先提一下啥是有状态登录 单台tomcat的情况下:编码的流程如下 前端提交表单里用户的输入的账号密码 后台接受,查数据库, 在数据库中找到用户的信息后,把用户的信息存放到session ...

  9. (二十四)c#Winform自定义控件-单标题窗体

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  10. Java初学心得(一)

    Java中基本组成单元是类,在类中又包含属性和方法. 每个应用程序都包含一个main()方法,main方法里的称为主类. 一,基本变化 ①全局变量:在类中的属性 局部变量:在方法中的属性 ②基本数据类 ...