题目传送门

位运算

设题目中序列 \(w_1,w_1 \& w_2,w_1 \& w_2 \& w_3,\dots,w_1 \& w_2 \& \dots \& w_n\) 为序列 \(A\)。

因为是数字一个一个 \(\&\) 到之前的结果上,所以可以知道 \(A\) 序列单调不增。

从给出的样例中发现,似乎没有答案超过 \(2\) 的情况

证明:

假设答案 \(>2\),则说明 \(A\) 序列至少中出现过了 \(0,1,2\),因为 \(A\) 序列单调不增,所以假设当前的 \(A_i\) 为 \(2\),必须后面的数出现 \(1\) 和 \(0\) 才可以。但 \(2\) 的二进制末位为 \(0\),无论怎么 \(\&\) ,后面的数也不可能出现 \(1\),假设不成立,所以答案不可能 \(>2\)。

结论:

答案为 \(0\),\(1\) 或 \(2\)。

判断答案

  • 首先考虑答案为 \(0\) 的情况,即 \(A\) 序列中没有出现过 \(0\):

\(A\) 序列中没有出现过 \(0\),即说明对于所有 \(w\),在二进制下至少有一位都是 \(1\),不然 \(\&\) 后就会变 \(0\)。

那么如何判断是否有一条路径上所有边权在二进制下至少有一位都是 \(1\)?

考虑用并查集维护。因为 \(w<=2^{30}\),所以可以开 \(30\) 个并查集,分别维护每一位上是 \(1\) 的边权所连接的点的集合,然后要判断求的两点是否在其中一张图中连通即可。

  • 再看答案为 \(1\) 的情况,即 \(A\) 序列中出现过 \(0\) 但没有出现过 \(1\):

\(A\) 序列中没有出现过 \(1\),即说明对于 \(A\) 序列前某一部分 \((i<k)\),\(a_i>1\),而 \(a_k\) 及之后都是 \(0\)。

先考虑如何保证 \(A\) 序列前某一部分 \((i<k)\),\(a_i>1\)。这个和答案为 \(0\) 的情况很像,只要所有 \(w_i(i<k)\) 中至少有一位都是 \(1\) 即可。但特别地,这一位不能是末位,否则 \(a_{k-1}\) 就变 \(1\) 了。

然后就只要判断之后是否有一条边可以使 \(\&\) 之后结果为 \(0\) 即可。

如何维护?

先上结论:只要保证末位有一个 \(0\) 即可。先把之前判断答案是否为 \(0\) 的并查集借过来,然后事先找好哪些边权末位为 \(0\),将与这些边相邻的点和一个虚点 \(0\) 连起来。如果后询问中出发点 \(u\) 可以和虚点 \(0\) 连通,那么答案就为 \(1\) 了。

证明:如果后询问中出发点 \(u\) 可以和虚点 \(0\) 连通,就意味着 \(u\) 在某一位上 (不为末位)可经过连续的几个 \(1\),保证了 \(a_i>1\)。然后可以走到一位末位为 \(0\) 的,\(a_i\) 的末位就会变成 \(0\)。之后,因为不存在某一位全部为 \(1\) 的(已经被判掉了),所以可以保证 \(a_i\) 的其他位最终也会变成 \(0\)。

这一部分有点绕,建议花点时间自己举几个例子好好理解一下。

  • 最后,都不是这两种情况的答案就为 \(2\)。

那么,如何方便地实现并查集?

便利の并查集

可以写到一个结构体里。(涨芝士了

比如:

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;
}

【题解】CF1659E AND-MEX Walk的更多相关文章

  1. Usaco2012-2013 金组 题解 (暂缺Hill walk以及Figue eight)

    https://files.cnblogs.com/files/Winniechen/usaco2012-2013.pdf 做的不是很好,还请见谅! 如果有什么疑问,可以QQ上找我. QQ号:1967 ...

  2. CF1139E Maximize Mex 题解【二分图】

    我发现我有道叫[SCOI2010]连续攻击游戏的题白写了.. Description There are \(n\) students and \(m\) clubs in a college. Th ...

  3. Google Kick Start 2019 C轮 第一题 Wiggle Walk 题解

    Google Kick Start 2019 C轮 第一题 Wiggle Walk 题解 题目地址:https://codingcompetitions.withgoogle.com/kickstar ...

  4. [HG]walk 题解

    前言 学长博客划水,抄题解,差评. 于是我来重新写一篇正常的题解,虽然解法跟标程不一样,但是复杂度是一样的. 题面 题目描述 在比特镇一共有\(n\)个街区,编号依次为\(1\)到\(n\),它们之间 ...

  5. BZOJ3339:Rmq Problem & BZOJ3585 & 洛谷4137:mex——题解

    前者:https://www.lydsy.com/JudgeOnline/problem.php?id=3339 后者: https://www.lydsy.com/JudgeOnline/probl ...

  6. BZOJ3076 & 洛谷3081:[USACO2013 MAR]Hill Walk 山走——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3076 https://www.luogu.org/problemnew/show/P3081#sub ...

  7. 题解报告:hdu 1142 A Walk Through the Forest

    题目链接:acm.hdu.edu.cn/showproblem.php?pid=1142 Problem Description Jimmy experiences a lot of stress a ...

  8. csp-s模拟65Simple,Walk, Travel,棋盘题解

    题面:https://www.cnblogs.com/Juve/articles/11639923.html simple: 考试时只想到的暴力exgcd判断 考虑n,m互质的情况: 我们枚举y,对于 ...

  9. 洛谷4137 mex题解 主席树

    题目链接 虽然可以用离线算法水过去,但如果强制在线不就gg了. 所以要用在线算法. 首先,所有大于n的数其实可以忽略,因为mex的值不可能大于n 我们来设想一下,假设已经求出了从0到n中所有数在原序列 ...

随机推荐

  1. 从0到1写一款自动为Markdown标题添加序号的Jetbrains插件

    1. markdown-index 最近做了一个Jetbrains的插件,叫markdown-index,它的作用是为Markdown文档的标题自动添加序号,效果如下: 目前已经可以在Jetbrain ...

  2. ERROR: column "xxxxxx" does not exist解决办法

    今天在写PostgreSQL语句时候发现运行这个代码 SELECT t1.equipid, t2.equipname, t1.bigtype, t1.smalltype FROM pdw_gh_pro ...

  3. std::atomic和std::mutex区别

    ​ ​std::atomic介绍​ ​模板类std::atomic是C++11提供的原子操作类型,头文件 #include<atomic>.​在多线程调用下,利用std::atomic可实 ...

  4. 基于anaconda3的Pytorch环境搭建

    安装anaconda3,版本选择新的就行 打开anaconda prompt创建虚拟环境conda create -n pytorch_gpu python=3.9,pytorch_gpu是环境名称, ...

  5. 使用SSH连接Windows Server

    之前发过一篇在Windows Server上启用SSH服务器的文章.最近正好有这个需求,需要使用密钥免密登录服务器,试了一下,发现之前的方法不行了.需要再修正一些文件权限. 需要使用Repair-Au ...

  6. 2、String类

    String类 String 对象用于保存字符串,也就是一组字符序列 字符串常量对象是用双引号括起来的字符序列,例如:"你好"."12.07"."bo ...

  7. MinIO分布式集群部署方式

    文章转载自:https://blog.51cto.com/u_10950710/4843738 关于分布式集群MinIo 单机Minio服务存在单点故障,如果是一个有N块硬盘的分布式Minio,只要有 ...

  8. 100个Linux Shell脚本经典案例(附PDF)

    转载自:https://mp.weixin.qq.com/s/tCKAM67_7K7q2vJthaIsDQ 原文链接:https://wenku.baidu.com/view/4f089430a116 ...

  9. Prometheus使用nginx 设置二级路径反向代理

    1.nginx 设置 location /promethues/ { proxy_pass http://10.xx.xxx.55:9090/prometheus/; } 2.设置prometheus ...

  10. 使用KubeOperator安装k8s集群后,节点主机yaml文件路径

    [root@k8s-develop-master-1 kubernetes]# cd /etc/kubernetes [root@k8s-develop-master-1 kubernetes]# l ...