首页 > 其他分享 >Luogu P9869 NOIp2023 三值逻辑 题解 [ 绿 ] [ 带权并查集 ]

Luogu P9869 NOIp2023 三值逻辑 题解 [ 绿 ] [ 带权并查集 ]

时间:2024-11-19 22:07:28浏览次数:1  
标签:P9869 三值 int 题解 查集 祖先 tof 节点 tod

三值逻辑:有点坑并且细节较繁琐,但有点板子的并查集。

修改操作

发现对于每个点,只有对他的最后一次操作才是有用的,所以记录下最终的祖先即可。

然而这里并不能用并查集来实现,因为并查集它具有的是传递性,无论你路不路径压缩,每次修改一个父节点时它的子节点一定会被修改,所以我们不能使用并查集。

但是可以使用并查集相关思想。

首先我们建立虚拟源点 \(n+1\) 表示 \(T\),\(n+2\) 表示 \(U\)。到某个点的距离为奇数时表示与这个点的值相反,为偶数则表示与这个点的值相等。

每次修改后,我们都直接指向父节点的祖先节点。为啥祖先节点就可以呢?因为此时祖先节点是未被修改的,而根据题目中“使得每个变量初始值与最终值相同”,所以这里跟祖先节点连边相当于和祖先节点的初值连边。自然是正确的了。

upd:这里其实可以用并查集,但是要时时刻刻路径压缩,每 combine 一次就要压一次。

注意,本题的先后问题主要还是通过路径压缩到祖先节点而不是父节点来解决的。

判断合法性

对于直接连向 \(U\) 的连通块,最终的结果一定是 \(U\)。

其余如果出现矛盾的连通块,最终的结果也一定全部是 \(U\)。这个的实现,只需要每次合并的时候判断一下到祖先节点的距离就好了。

时间复杂度 \(O(tn)\)。

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pi;
int n,m,tof[100005],tod[100005],f[100005],d[100005];
//n+1: T ,n+2: U
bitset<100005>ilg;
int findf(int x)
{
    if(f[x]!=x)
    {
        int orif=f[x];
        f[x]=findf(f[x]);
        d[x]=(d[orif]^d[x]);
    }
    return f[x];
}
void combine(int x,int y,int td)
{
    int fx=findf(x),fy=findf(y);
    if(fx!=fy)
    {
        d[fx]=(d[y]^td^d[x]);
        f[fx]=fy;
    }
}
void init()
{
    for(int i=1;i<=n+2;i++)f[i]=i,d[i]=0;
}
void solve()
{
    cin>>n>>m;
    for(int i=1;i<=n+2;i++)
    {
        tof[i]=i;
        tod[i]=0;
    }
    ilg.reset();
    for(int i=1;i<=m;i++)
    {
        int a,b;
        char v;
        cin>>v>>a;
        if(v=='+')
        {
            cin>>b;
            tof[a]=tof[b];
            tod[a]=tod[b];
        }
        else if(v=='-')
        {
            cin>>b;
            tof[a]=tof[b];
            tod[a]=(tod[b]^1);            
        }
        else if(v=='T')
        {
            tof[a]=n+1;
            tod[a]=0;
        }
        else if(v=='F')
        {
            tof[a]=n+1;
            tod[a]=1;            
        }
        else
        {
            tof[a]=n+2;
            tod[a]=0;
        }
    }
    init();
    for(int i=1;i<=n;i++)
    {
        if(findf(i)==findf(tof[i]))
        {
            if(tod[i]!=(d[i]^d[tof[i]]))ilg[findf(i)]=1;
        }
        combine(i,tof[i],tod[i]);
    }
    int ans=0;
    for(int i=1;i<=n;i++)if(findf(i)==n+2||ilg[findf(i)])ans++;
    cout<<ans<<'\n';
}
int main()
{
    //freopen("tribool.in","r",stdin);
    //freopen("tribool.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int x,t;
    cin>>x>>t;
    while(t--)solve();
    return 0;
}

标签:P9869,三值,int,题解,查集,祖先,tof,节点,tod
From: https://www.cnblogs.com/zhr0102/p/18555719

相关文章

  • CF2037E 题解
    CF2037E题解题意给定一个长度为\(n\)的\(01\)串,定义\(f(l,r)\)为\(l\)到\(r\)区间内\(01\)子序列的数量,通过最多\(n\)次交互,确定这个\(01\)串的构成。分析可以从莫队的思想,也就是增量,来思考如何解决。如果说我们已经知道了\(f(l,r)=ans\),接下来我们询问......
  • CF 1253 题解
    CF1253题解ASinglePush考虑令\(d_i=b_i-a_i\),那么合法当且仅当\(d\)在一个前缀和一个后缀都是\(0\),其余地方值一致并且非负.BSillyMistake注意到能作一次划分的时候立即划分一定更优,因为这样就不会因为潜在的一天两次进入办公室而得不到答案.贪心的模拟即可.......
  • 2024年全国职业院校技能大赛中职组《大数据应用与服务赛项》赛项赛题解析第三模块
      职业院校技能大赛大数据应用与服务交流群:q743959419目录模块三:数据分析与可视化任务一:数据分析与可视化子任务一:柱状图数据分析与可视化子任务二:折线图数据分析与可视化子任务三:饼图数据分析与可视化子任务四:雷达图数据分析与可视化任务二:数据分析子任务一:Excel......
  • Public NOIP Round #6 D 排序 题解
    Description今天是YQH的生日,她得到了一个\(1\simn\)的排列作为礼物。YQH是一个有强迫症的女孩子,她希望把这个排列从小到大排序,具体的,她可以进行这样的操作:把\([1,n]\)分成若干个区间,假如是\(m\)段,依次为\([l_1,r_1],[l_2,r_2],\dots,[l_m,r_m]\),其中\(l_1=1,r_m=......
  • 【题解】洛谷:P4805 [CCC2016] 合并饭团
    P4805[CCC2016]合并饭团希望写完这篇题解能真正地会这种题。合并两个的操作很像合并石子的操作,确实直接那么做就可以,但三个怎么办呢,暴力做法就是枚举中间两个端点然后转移,但是这样复杂度太大了有\(O(n^4)\)。于是搬出我们的双指针,在面对区间问题时双指针可以有效地解决问题,......
  • UOJ918 【UR #28】偷吃蛋糕 题解
    题目描述\(n\)层蛋糕,第\(i\)层大小\(c_i\),保证\(c_i\)单调不增。初始你有第\(1\)层蛋糕,然后重复以下操作,直至没有蛋糕:吃掉最大的一层蛋糕,记其大小为\(x\)。如果还有至少\(x\)层蛋糕没有给你,主办方会按编号升序给你接下来的\(x\)层蛋糕。如果只有\(y\)层蛋......
  • C -- [vs2019] C2440 错误,无法从 const char[] 转换为 char*问题解决
    https://blog.csdn.net/weixin_45525272/article/details/118699716原因新标准中,不能把指针指向一串常量解决方案一:引入[]char*str=“helloworld”;改成:charstr_tmp[]=“helloworld”;char*str=str_tmp;方案二:加constchar*str=“helloworld”;改成:......
  • ABC380 DEFG 题解
    ABC380题解赛时秒了ABCDE(好吧其实还是略有卡顿,写完大概花了55min),看到F有博弈直接跑了,没注意到数据范围这么小,看到G一下就会了大致思路,但具体细节上搞复杂了,快写完了才发现不用维护这么多(恼),然后因为某些神秘错误现在都还没有调出来。至于F,赛后看见数据范围这么小,自己独立......
  • マス目と整数 题解
    前言题目链接:洛谷;AtCoder。题意简述给你一个\(n\timesm\)的矩形\(a\),其中已经有\(q\)个位置填上了数,你需要为剩下的位置分别填上一个非负整数,使得最终任意一个\(2\times2\)的子矩形内,左上角的数加右下角的数等于右上角的数加左下角的数,即\(\foralli\in[1,n),j\in......
  • CF715B Complete The Graph 题解
    Description给\(n\)点\(m\)边的无向图,\(L\),\(s\),\(t\)。修改\(m\)条边中边为\(0\)的边,使满足\(s,t\)的最短路长度是\(L\),且输出答案的时候边为\(0\)的边的权值必须在\([1,10^{18}]\)内。Solution考虑怎么判有无解。容易发现将所有未知边边权设为\(10^{18}\),......