【笔记】CF1659E AND-MEX Walk 及相关
题目传送门
位运算
设题目中序列
因为是数字一个一个
从给出的样例中发现,似乎没有答案超过
证明:
假设答案
结论:
答案为
判断答案
- 首先考虑答案为
的情况,即 序列中没有出现过 :
那么如何判断是否有一条路径上所有边权在二进制下至少有一位都是
考虑用并查集维护。因为
- 再看答案为
的情况,即 序列中出现过 但没有出现过 :
先考虑如何保证
然后就只要判断之后是否有一条边可以使
如何维护?
先上结论:只要保证末位有一个
证明:如果后询问中出发点
- 最后,都不是这两种情况的答案就为
。
那么,如何方便地实现并查集?
便利の并查集
可以写到一个结构体里。(涨芝士了
比如:
struct DSU{
int fa[100005];
DSU(){for(int i=0;i<=100000;i++)fa[i]=i;} //初始化
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} //find
void merge(int x,int y){fa[find(x)]=find(y);} //合并
bool query(int x,int y){return find(x)==find(y);} //判断
}x[35];
合并:
x[i].merge(u,v);
判断联通:
if(x[i].query(u,v))
要开多个并查集时很方便,比写二维数组要清楚。
完整代码
#include<bits/stdc++.h>
using namespace std;
int n,m,q,u,v,w;
bool mark[100005];
struct DSU{ //还是喜欢不压行
int fa[100005];
DSU(){
for(int i=0;i<=100000;i++) fa[i]=i;
}
int find(int x){
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
void merge(int u,int v){
fa[find(u)]=find(v);
return ;
}
bool query(int u,int v){
return find(u)==find(v);
}
}x[35],y[35];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
for(int j=0;j<30;j++){
if((w>>j)&1) x[j].merge(u,v); //j位是1的连起来
}
if(!(w&1)) mark[u]=mark[v]=1; //末位不是1做标记
}
for(int i=1;i<=30;i++){ //从1开始
y[i]=x[i];
for(int j=1;j<=n;j++){
if(mark[j]) y[i].merge(j,0); //有标记和0连
}
}
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%d%d",&u,&v);
bool fl=0;
for(int j=0;j<30;j++){ //从0开始
if(x[j].query(u,v)){
printf("0\n"),fl=1;
break;
}
}
if(fl) continue;
for(int j=1;j<30;j++){ //从1开始
if(y[j].query(u,0)){
printf("1\n"),fl=1;
break;
}
}
if(fl) continue;
printf("2\n");
}
return 0;
}
特别鸣谢:巨佬 Mine_King 的 代码 帮助我理解了解题方法
查重率 100% qwq
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话