题面

CF原版
洛谷中文题面

分析

通过观察我们可以发现,这是一道 2-SAT 问题,因为我们有 q 个两两相关的限制条件,于是我们可以考虑建图来跑 (于是建图这一步这么快就出来了)。

因为我们的限制条件是按位或,因此我们可知在二进制下各个位是相互独立的,于是我们可以分开讨论,并且我们发现我们只需要对每个位上都求出字典序最小的情况,我们就得到了整个的字典序最小。

建图

我们考虑怎么建图:由于是 2-SAT 问题,假定每个数的当前位为点,那么每一对限制条件就是一条无向边(因为他们的限制是相互的)。

我们分 3 中情况讨论:

  1. 已经确定:通过观察我们可以发现,如果给定的 a==ba == ba==b 那么我们就已经可以确定 ans[a]=xans[a] = xans[a]=x(ans即为最终输出结果),注意 a 是下标(注意看题)。那么我们在分位讨论的时候只需要给他所对应的点上一个特殊标记,告诉程序我们将不再动他即可(比如为 1 就给他赋值为 2,为 0 就直接赋值为 0,因为我们后面将只处理权值为 1 的节点)。

  2. 限制为0:在一对限制条件中,我们不难发现,如果 x 在这一位是 0,那么我们就可以断定 ans[a] 和 ans[b] 的这一位都是 0(由按位或的性质)。那么我们可以在建图的时候就直接让这两个点的权值赋为 0,然后再也不动他即可。(由于要求字典序最小,于是已经被赋为 0 的位我们将不会再动)。

  3. 限制为1:再考虑 x 这一位是 1 的情况,我们先假定除了以上两种特殊处理的点以外的点的权值都为 1,然后将每一对这样的限制连上边(上面两种已经确定的情况可以不建)。我们从节点 1 开始(也就是对应原序列的第一个数)遍历所有他所连向的点,如果其中由任何一个权值为 0(前面赋的初值,或者后面处理的),那么我们可以确定这个点只能为 1。否则我们就把它赋为 0(为了保证字典序最小)。最后所有点更新完之后更新答案即可。(注意:已经赋值为 0 或 2 的点我们将不会再动,因为他们已经确定了)。

当所有位都跑完我们就得到了最终答案。

注意:如果某个点被孤立了(没有连边),那么他直接为 0 是最优的。

eg. 我们以原题中的样例一为例:

上图中边上的权值表示限制中的 x 这一位是什么。

代码实现

//省略快读和头文件
#define Ql Qualifications//为了简写用
int T;struct Edge {int hd[MAXN];int nxt[MAXN << 2], to[MAXN << 2];int tot = 0;void Add(int x, int y) {nxt[++tot] = hd[x];hd[x] = tot;to[tot] = y;}
}e;int n, q;
int ans[MAXN];struct Qualifications {int a, b, x;
}p[MAXN << 1];int dig[MAXN];
void Solve(int pos)
{memset(e.hd, 0, sizeof(e.hd));//记得清空e.tot = 0;for(int i = 1; i <= n; i++)dig[i] = 1;for(int i = 1; i <= q; i++) {if(p[i].a == p[i].b) {if((p[i].x >> pos) & 1)dig[p[i].a] = 2;//表示为 1,且固定不再修改elsedig[p[i].a] = 0;//如果是 0,直接为 0 即可,因为我们本来就不动他 continue;}if((p[i].x >> pos) & 1) {//如果是 1 就说明需要连边来判断如何填 e.Add(p[i].a, p[i].b);e.Add(p[i].b, p[i].a);}else {dig[p[i].a] = dig[p[i].b] = 0;//如果是 0 那么直接赋值为 0 即可,由按位或的性质 }}for(int x = 1; x <= n; x++) {if(dig[x] == 0 || dig[x] == 2)continue;//这两种都是已经固定的bool flag = true;//表示可以更改为 0 for(int i = e.hd[x]; i; i = e.nxt[i]) {int y = e.to[i];if(dig[y] == 0) {//只要连向的点有一个是 0 就说明他一定是 1 flag = false;break;}}if(flag || !e.hd[x])//否则将他赋值为 0 一定更优(字典序最小) dig[x] = 0;//同样如果这个点是独点,那么他一定为 0 更优 }for(int i = 1; i <= n; i++)ans[i] |= (dig[i] > 0) * (1 << pos);
}int main()
{n = inpt(), q = inpt();for(int i = 1; i <= q; i++) {int a = inpt(), b = inpt(), x = inpt();if(a == b)//表示这一个已经确定了 ans[a] = x;p[i] = Ql{a, b, x};//看不懂就看第1行和第19行}for(int i = 0; i < 31; i++)//分位做 Solve(i);for(int i = 1; i <= n; i++)printf("%d ", ans[i]);return 0;
}

CF1715D 2+ doors 题解相关推荐

  1. Vulnhub靶场题解

    Vulnhub简介 Vulnhub是一个提供各种漏洞环境的靶场平台,供安全爱好者学习渗透使用,大部分环境是做好的虚拟机镜像文件,镜像预先设计了多种漏洞,需要使用VMware或者VirtualBox运行 ...

  2. Educational Codeforces Round 132 div.2 A-F题解

    视频讲解:TBD A. Three Doors 题目大意 有 333 个门和 333 把对应的钥匙.其中 222 把钥匙分别在 222 扇门后,111 把在手上.打开门才能获得门后的钥匙,问能否打开所 ...

  3. Codeforces Round #816 (Div. 2) D. 2+ doors

    D. 2+ doors 题意: 构造一个字典序最小且长度为 n n n 的序列满足 q q q 个限制. 限制为 a i ∣ a j = x a_i | a_j = x ai​∣aj​=x. 题解: ...

  4. 老鱼的-kuangbin专题题解

    kuangbin专题问题一览 专题一 简单搜索 POJ 1321 棋盘问题 POJ 2251 Dungeon Master POJ 3278 Catch That Cow POJ 3279 Flipt ...

  5. [JS][dfs]题解 | #迷宫问题#

    题解 | #迷宫问题# 题目链接 迷宫问题 题目描述 定义一个二维数组 N*M ,如 5 × 5 数组下所示: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 1, 1 ...

  6. [JS][dp]题解 | #打家劫舍(一)#

    题解 | #打家劫舍(一)# 题目链接 打家劫舍(一) 题目描述 描述 你是一个经验丰富的小偷,准备偷沿街的一排房间,每个房间都存有一定的现金,为了防止被发现,你不能偷相邻的两家,即,如果偷了第一家, ...

  7. [JS]题解 | #魔法数字#

    题解 | #魔法数字# 题目链接 魔法数字 题目描述 牛妹给牛牛写了一个数字n,然后又给自己写了一个数字m,她希望牛牛能执行最少的操作将他的数字转化成自己的. 操作共有三种,如下: 在当前数字的基础上 ...

  8. [JS]题解 | #岛屿数量#

    题解 | #岛屿数量# 题目链接 岛屿数量 题目描述 时间限制:1秒 空间限制:256M 描述 给一个01矩阵,1代表是陆地,0代表海洋, 如果两个1相邻,那么这两个1属于同一个岛.我们只考虑上下左右 ...

  9. [JS] 题解:提取不重复的整数

    题解:提取不重复的整数 https://www.nowcoder.com/practice/253986e66d114d378ae8de2e6c4577c1 时间限制:1秒 空间限制:32M 描述 输 ...

  10. 洛谷-题解 P2672 【推销员】

    独门思路!链表加优先队列! 这题一望,贪心是跑不掉了,但是我贪心并不好,所以想到了一个复杂一些但思路更保稳的做法 思路: 1 因为是离线操作,所以我们可以倒着求,先求x=n的情况,因为那样直接就知道了 ...

最新文章

  1. 【NLP】听李宏毅点评GPT-3:来自猎人暗黑大陆的模型
  2. 深度探索I/O完成端口
  3. extjs 表格数据重新加载_一个简单的更改让PyTorch读取表格数据的速度提高20倍:可大大加快深度学习训练的速度...
  4. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations
  5. tornado cookie和session
  6. Cinder - 云硬盘加密
  7. java sin函数图像_java中怎样绘制正弦函数图象
  8. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_07 缓冲流_7_练习_对文本的内容进行排序...
  9. lisp用entmake生产圆柱体_蚌埠踏步板钢盖板沟盖板生产加工厂家材质齐全-老友网...
  10. 北京市计算机自考,【北京自考计算机上机考今起举行】- 环球网校
  11. java 如何执行dig 命令_linux dig 命令使用方法
  12. 操作系统课堂笔记(4)进程管理之多道程序设计和进程
  13. Python 局域网扫描存活主机开放端口
  14. 作为一名菜鸟的学习分享
  15. 大小写金额转换html,小写金额转为大写金额JS代码怎么写呢?
  16. 【C语言】贪吃蛇小游戏代码详解
  17. Spring Boot Redis 实现分布式锁,真香,你掌握了多少?
  18. pfSense与CARP的硬件冗余
  19. 【医学影像 | 个人记录】骨盆
  20. Unity3d项目入门之虚拟摇杆

热门文章

  1. java 正数转负数_Java程序将正整数转换为负数,并将负整数转换为正数
  2. no interpreter
  3. 使用分身术变身术创建新进程
  4. 公众号丶服务号丶订阅号三者间的区别
  5. 中台战略-第五章、中台建设方法论
  6. Nacos 中配置 Map 类型,不香
  7. JavaScript(JS)的简单了解
  8. HBuilder打包App教程
  9. vast显示不出来服务器,VAST实用小知识?
  10. choco 使用详解