• 239. 奇偶游戏


    小 A 和小 B 在玩一个游戏。

    首先,小 A 写了一个由 0 和 1 组成的序列 S,长度为 N。

    然后,小 B 向小 A 提出了 M 个问题。

    在每个问题中,小 B 指定两个数 l 和 r,小 A 回答 S[l∼r] 中有奇数个 1 还是偶数个 1。

    机智的小 B 发现小 A 有可能在撒谎。

    例如,小 A 曾经回答过 S[1∼3] 中有奇数个 1,S[4∼6] 中有偶数个 1,现在又回答 S[1∼6] 中有偶数个 1,显然这是自相矛盾的。

    请你帮助小 B 检查这 M 个答案,并指出在至少多少个回答之后可以确定小 A 一定在撒谎。

    即求出一个最小的 k,使得 01 序列 S 满足第 1∼k 个回答,但不满足第 1∼k+1 个回答。

    输入格式

    第一行包含一个整数 N,表示 01 序列长度。

    第二行包含一个整数 M,表示问题数量。

    接下来 M 行,每行包含一组问答:两个整数 l 和 r,以及回答 even 或 odd,用以描述 S[l∼r] 中有偶数个 1 还是奇数个 1。

    输出格式

    输出一个整数 k,表示 01 序列满足第 1∼k 个回答,但不满足第 1∼k+1 个回答,如果 01 序列满足所有回答,则输出问题总数量。

    数据范围

    N≤109,M≤5000

    输入样例:
    10
    5
    1 2 even
    3 4 odd
    5 6 even
    1 6 even
    7 10 odd
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    输出样例:
    3
    
    • 1
    思路:
    • 边权并查集
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

    • 扩展域

    在这里插入图片描述
    在这里插入图片描述

    代码1:
    // 边权并查集 往广义的来说,并查集维护的是俩俩元素之间的信息。(这个信息,可以是是否联通,也可以是奇偶性是否相同,还可以是两点距离等等)
    #include 
    using namespace std;
    
    const int N = 10010;
    
    int n, m;
    int p[N], d[N];
    
    unordered_map<int, int> S;
    int get(int x) // 哈希
    {
        if (S.count(x) == 0)
            S[x] = ++n;
        return S[x];
    }
    
    int find(int x)
    {
        if (p[x] != x)
        {
            int root = find(p[x]);
            d[x] ^= d[p[x]];  // 到根节点的路径长度 以根节点为对照点异或
            p[x] = root;
        }
        return p[x];
    }
    
    int main()
    {
        cin >> n >> m;
        n = 0;
    
        for (int i = 0; i < N; i++)
            p[i] = i;
    
        int res = m;
        for (int i = 1; i <= m; i++)
        {
            int a, b;
            string type;
            cin >> a >> b >> type;
            a = get(a - 1), b = get(b);
    
            int t = 0;
            if (type == "odd")
                t = 1;
    
            int pa = find(a), pb = find(b);
            if (pa == pb) // 在一个集合中则判断
            {
                if (d[a] ^ d[b] != t) 
                {
                    res = i - 1;
                    break;
                }
            }
            else  // 否则两集合相连接
            {
                p[pa] = pb;
                d[pa] = d[a] ^ d[b] ^ t;  // 通过两者的奇偶性是否相同赋值
            }
        }
    
        cout << res << endl;
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    代码2:
    // 扩展域分别是各个条件
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    const int N = 2e4 + 10, Base = N / 2;
    
    int n, m;
    int p[N], d[N];
    unordered_map<int, int> S;
    
    int get(int x)
    {
        if (S.count(x) == 0)
        {
            S[x] = ++n;
        }
        return S[x];
    }
    
    int find(int x)
    {
        if (p[x] != x)
        {
            p[x] = find(p[x]);
        }
        return p[x];
    }
    
    int main()
    {
        cin >> n >> m;
        n = 0;
    
        for (int i = 0; i < N; i++)
        {
            p[i] = i;
        }
    
        int res = m; //如果无矛盾, 输出问题数量, 初始的时候为m
        for (int i = 1; i <= m; i++)
        {
            int a, b;
            string type;
            cin >> a >> b >> type;
            a = get(a - 1), b = get(b); // s[a-1], s[b]
            if (type == "even")
            {
                if (find(a + Base) == find(b))
                {
                    res = i - 1;
                    break;
                }
                p[find(a)] = find(b);
                p[find(a + Base)] = find(b + Base);
            }
            else
            {
                if (find(a) == find(b))
                {
                    res = i - 1;
                    break;
                }
                p[find(a + Base)] = find(b);
                p[find(a)] = find(b + Base);
            }
        }
        cout << res << endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
  • 相关阅读:
    未来五十年,智能科技将如何改变传统行业格局?
    C# EPPlus导出dataset----Excel1
    02Linux各目录及每个目录的详细介绍
    程序放在哪儿?
    【Rust 日报】2023-11-19 solars:可视化太阳系
    Mysql的B+树高度计算
    Python中的POST请求参数
    Compose中的“ViewPager“和Banner
    MPEG vs JPEG
    Python二级题:MOOC学校名单|关键词提取和查找
  • 原文地址:https://blog.csdn.net/segegse/article/details/126614019