CF1044D Deduction Queries
题目大意
现在有一个大小为 的数组,每个位置都有一个值,每次有两种操作:
1 x y z
表示告诉你 到 区间的所有值异或和为 。(如果和上次告诉你的矛盾,就可以当做没说。)2 x y
问你区间 到 的所有值的异或和是多少,如果你不知道就输出-1
。
解题思路
有什么东西可以维护矛盾信息呢?
带权并查集!!!
定义 为 的父亲, 表示 异或 的值。
每次告诉我一个区间异或值,我只需要对两个端点进行操作就可以了,比如题目告诉我 1 a b x
,我先通过路径压缩找到 ,,如果 ,给的信息无用,就不需要操作了,否则,令 的父亲等于 ,那么怎么求 呢,,那么 ,,因为 ,那么 ,解决了这一步,就没问题了,每次答案即为 。
具体参考代码。
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;
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18122092