P9869 [NOIP2023] 三值逻辑 题解
NOIP2023 T2 三值逻辑 题解
思路
乍一看好像很并查集,而且不太难,但是,
注意到:按顺序运行这 \(m\) 条语句
事情并没有那么简单。
比如说如下情况:
x1:=T
x2:=x1
x1:=F
这时,\(x_2\)就不能简单地指向\(x_1\),否则当\(x_1\)被修改时,\(x_2\)也会被修改。
那么如何解决这个问题呢?
其实有点可持久化的感觉。我们可以对于每次修改\(x_1\)时,为它新建一个版本。以后所有形如\(x_2:=x_1\)的赋值操作,\(x_2\)都指向最新的版本。可以以边的形式存储它们的对应关系,\(x_2:=x_1\)则由\(x_2\)向\(x_1\)指一条边权为0的边(下文称为正边),\(x_2:=-x_1\)则由\(x_2\)向\(x_1\)指一条边权为1的边(下文称为负边)(这些边权是干什么的?这是一会儿要用到的神奇妙妙工具)。最终的产物像若干个栈。每个位置都有一个栈,每个栈上都摞着若干个节点。
(图挂了)
像这样。有些东西没画,各位自行脑补。
可以观察到它是一个森林,森林中每棵树上的节点的值都相等。
题干中说,要让执行了所有语句后所有变量的最终值和初始值相等。那么我们可以从每个栈的栈底向栈顶指一条正边。于是我们得到了若干个环。最终的图也就是若干基环树,但是本文中的做法并没有用到什么基环树,笔者也不会基环树。
我们要找到只能初始化为\(U\)的位置,那么什么时候一个位置只能被初始化为\(U\)呢?
第一种情况,它在最后一次赋值(“栈顶”)中被直接或间接赋值为\(U\)。这是显然的。
第二种情况,它的“栈底”(或“栈顶”)处在一个环里,且这个环中有奇数条负边。这也是显然的。
显然我们要集中精力求第二种。
依次对每一个位置进行DFS,如果DFS到被明确地赋值了的节点(形如\(x_1:=T\)),那么回溯时返回这个值,赋给回到的节点。否则返回0(也可以是-1或任何你喜欢的数。如果你也设为0,那么记得将数组初始化为-1)。
如果DFS到了一个环,且当前经过的负边个数减去上一次到这个点时的负边个数是一个奇数,那么赋值为\(U\)。可以在DFS时以参数形式传递当前经过的负边个数,用数组存储上一次到某位置时的负边个数。这时我们的负边权值为1就派上了用场,路径的权值和即是负边个数。
于是此题得解。
注意,当出现自环时,不能简单粗暴地忽略或认为无解,这样会挂40分(别问我怎么知道的);而是把它也加进图里。因为它在栈中相当于上下两节点之间的连边,是可以存在的。此时注意赋值顺序,不要像笔者一样先把节点入栈再从该节点向栈顶连边。
实现
原谅我抽象的码风
#include <iostream>
#include <cstring>
#define N 300005
int to[N],top[N],wt[N];
bool vis[N];
int a[N];
int tlen[N];
int dfs(int x,int len)
{
if(a[x]>=0)
return a[x];
if(vis[x])
{
if((len-tlen[x])&1)
return a[x]=3;
return a[x]=0;
}
vis[x]=1;
tlen[x]=len;
if(!to[x])
return a[x]=0;
int tmp=dfs(to[x],len+wt[x]);
if(tmp==3||tmp==0)
a[x]=tmp;
else
{
if(wt[x])
a[x]=3-tmp;
else
a[x]=tmp;
}
vis[x]=0;
return a[x];
}
int main()
{
int c,t;
scanf("%d%d",&c,&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
memset(top,0,sizeof(top));
memset(to,0,sizeof(to));
memset(a,-1,sizeof(a));
memset(vis,0,sizeof(vis));
memset(tlen,0,sizeof(tlen));
int cnt=0;
for(int i=1;i<=n;i++)
top[i]=++cnt;
for(int i=1;i<=m;i++)
{
char opt;
std::cin>>opt;
if(opt=='+')
{
int u,v;
scanf("%d%d",&u,&v);
cnt++;
to[cnt]=top[v];
top[u]=cnt;
wt[cnt]=0;
}
if(opt=='-')
{
int u,v;
scanf("%d%d",&u,&v);
cnt++;
to[cnt]=top[v];
top[u]=cnt;
wt[cnt]=1;
}
if(opt=='T'||opt=='F'||opt=='U')
{
int v;
scanf("%d",&v);
top[v]=++cnt;
if(opt=='T')
a[cnt]=1;
else if(opt=='F')
a[cnt]=2;
else
a[cnt]=3;
}
}
for(int i=1;i<=n;i++)
if(top[i]!=i)
to[i]=top[i],wt[i]=0;
for(int i=1;i<=n;i++)
if(a[i]<0)
dfs(i,0);
int ans=0;
for(int i=1;i<=n;i++)
if(a[i]==3)
ans++;
printf("%d\n",ans);
}
}
\]
P9869 [NOIP2023] 三值逻辑 题解的更多相关文章
- 你真的会玩SQL吗?让人晕头转向的三值逻辑
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
- CF100965C题解..
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
随机推荐
- 新型大语言模型的预训练与后训练范式,阿里Qwen
前言:大型语言模型(LLMs)的发展历程可以说是非常长,从早期的GPT模型一路走到了今天这些复杂的.公开权重的大型语言模型.最初,LLM的训练过程只关注预训练,但后来逐步扩展到了包括预训练和后训练在内 ...
- 使用阿里的ARTHAS跟踪方法耗时
使用命令跟踪一个方法的耗时 在arthas 命令行下输入命令 trace 类全路径 监控的方法 trace com.redxun.bpm.core.service.BpmInstServiceImpl ...
- oracle中id自增长(转)
首先,你要有一张表! CREATE TABLE example( ID Number(4) NOT NULL PRIMARY KEY, NAME VARCHAR(25), PHONE VARCHAR( ...
- 中电金信鲸视:以AI视觉技术为复杂行业场景装上“火眼金睛”
作为人工智能和计算机视觉的交叉领域,智能视觉通过仿生人类视觉机能,对不同形式的视觉输入进行处理.理解和决策.现今,智能视觉已成为应用广泛.市场覆盖大.形式多样的产业方向,得到了国家政策的大力支持. ...
- tar/zip命令加密压缩
回到顶部 场景 Centos6下使用加密压缩,可以从A机器到B机器解压. 可用在kali上解压就不行. 回到顶部 命令 解包 tar zxvf FileName.tar 打包 tar czvf Fil ...
- @EnableWebMvc 注解会让Swagger无效访问的问题
在工作中,通过Swagger2对项目的controller进行配置,以便于用户测试restful服务接口提高开发效率. 但是今天却出现了一个让我匪夷所思的问题就是在配置类里面加上@EnableWebM ...
- java - Powermock-Failed to transform class with name...ArrayIndexOutOfBoundsException: 3
I'm trying to run a junit test. i'm using: junit 4.10,easymock 3.0,powermock-core 1.4.10 (uses javas ...
- Qt开源作品41-网络调试助手增强版V2022
一.前言 做网络通信少不了网络收发数据,经常用到网络数据的调试相关工具,以便侦听数据用来判断数据是否正确,许久以前就发布过类似的工具,第一版大概在2013年,第二版大概在2017年,中间参考过不少的网 ...
- Windows下用CMake构建和编译第三方依赖库并向C:\Program Files\或C:\Program Files (x86)\目录下安装编译好的静态库(.lib)和动态链接库(.dll)时的步骤和注意事项
从CMake构建和编译第三方依赖库的步骤: 1.下载第三方依赖库的源码,并解压到指定的目录中. 2.在第三方依赖库的的源码所在的目录下(一般是src/目录下)创建一个文件夹build. 3.打开CMa ...
- 【OpenCV】features2d_converters.cpp:2:10: fatal error: common.h: 没有那个文件或目录
Linux环境下使用opencv的dnn模块调用yolov4遇到的坑(纯CPU)一.问题描述Ubuntu安装opencv4.4,第一次编译完成安装成功,发现编译时少加了几个选项,于是重新编译,结果报如 ...