CF1044D Deduction Queries

题目大意

现在有一个大小为 2302^{30} 的数组,每个位置都有一个值,每次有两种操作:

  • 1 x y z 表示告诉你 xxyy 区间的所有值异或和为 zz。(如果和上次告诉你的矛盾,就可以当做没说。)
  • 2 x y 问你区间 xxyy 的所有值的异或和是多少,如果你不知道就输出 -1

解题思路

有什么东西可以维护矛盾信息呢?

带权并查集!!!

定义 fafaaa 的父亲,r[a]r[ a ] 表示 aa 异或 fafa 的值。

每次告诉我一个区间异或值,我只需要对两个端点进行操作就可以了,比如题目告诉我 1 a b x,我先通过路径压缩找到 fafafbfb,如果 fa=fbfa=fb,给的信息无用,就不需要操作了,否则,令 fafa 的父亲等于 fbfb,那么怎么求 r[fa]r[fa] 呢,r[a]=axorfar[a]=a \operatorname{xor} fa,那么 fa=r[a]xorafa=r[a] \operatorname{xor} ar[fa]=faxorfb=r[a]xoraxorr[b]xorbr[fa]=fa \operatorname{xor} fb=r[a] \operatorname{xor}a \operatorname{xor} r[b] \operatorname{xor} b,因为 axorb=xa \operatorname{xor} b=x,那么 fa=r[a]xorr[b]xorxfa=r[a] \operatorname{xor} r[b] \operatorname{xor} x,解决了这一步,就没问题了,每次答案即为 rlxorrbr_l \operatorname{xor} r_b

具体参考代码。

CODE

#include <bits/stdc++.h>

using namespace std;

inline int read()
{
    int x = 0, w = 1;
    char ch = getchar();
    while (!isdigit(ch))
        ch = getchar();
    if (ch == '-')
        w = -1;
    while (isdigit(ch))
        x = ((x << 3) + (x << 1)) + ch - '0', ch = getchar();
    return x * w;
}

map<int, int> fa, num;

int n, l, r, x, last = 0, q, opt;

int find(int x)
{
    if (!fa.count(x))
        return x;
    int tmp = find(fa[x]);
    num[x] ^= num[fa[x]];
    fa[x] = tmp;
    return fa[x];
}

signed main()
{
    q = read();
    while (q--)
    {
        opt = read();
        if (opt == 1)
        {
            l = read();
            r = read();
            x = read();
            l ^= last, r ^= last, x ^= last;
            if (l > r)
                swap(l, r);
            --l;
            int xf = find(l), yf = find(r);
            if (xf != yf)
            {
                fa[yf] = xf;
                num[yf] = x ^ num[l] ^ num[r];
            }
        }
        else
        {
            l = read();
            r = read();
            l ^= last;
            r ^= last;
            if (l > r)
                swap(l, r);
            --l;
            int xf = find(l), yf = find(r);
            if (xf != yf)
            {
                last = 1;
                puts("-1");
            }
            else
            {
                last = num[l] ^ num[r];
                printf("%d\n", last);
            }
        }
    }
    return 0;
}
posted @ 2021-11-13 17:03  蒟蒻orz  阅读(3)  评论(0编辑  收藏  举报  来源