Description
Input
Output
Hint
Solution
看到判断真假条件的都要想到并查集了(哭
但是这里我并没有用并查集做法
考虑我们如果已经得到了目标序列a,并记录一个前缀异或数组s,则对于全部的询问l, r, k都要满足s[r]xor s[l-1]=k。那么我们对于一个操作l, r, k,若l-1和r同属于一个集合就判断他们之间的路径是否为k,若他们不属于同一个集合就连权为k的边合并
这里在合并的时候有一个技巧就是小的并上大的,这样每次dfs小集合更改异或值的时候就总的复杂度就是NlogN了
对于每一个独立的集合,只要任意一个数字确定了剩下的数字就都确定了。那么每个集合内第一个遇到的数字填0就可以了。注意一下这里的0是序列a的值,并不是前缀异或和s
Code
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define drp(i, st, ed) for (int i = st; i >= ed; i -= 1)
#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)
#define fill(x, t) memset(x, t, sizeof(x))
#define max(x, y) ((x)>(y)?(x):(y))
#define min(x, y) ((x)<(y)?(x):(y))
#define abs(x) ((x)<(0)?(-(x)):(x))
#define N 400001
#define E N << 2 | 1
#define L 11
struct edge {int x, y, w, next;} e[E];
int used[N], size[N], dis[N], fa[N], ls[N], edgeCnt = 0;
inline int read() {
int x = 0; char ch = getchar();
for(; ch<'0'||ch>'9'; ch=getchar());
for(; ch<='9'&&ch>='0'; (x*=10)+=ch-'0',ch=getchar());
return x;
}
inline void writeln(int x){
char ch[L] = {}; int i = 0;
do {ch[++ i] = '0' + x % 10;} while (x /= 10);
while (i) putchar(ch[i --]);
putchar('\n');
}
inline void addEdge(int x, int y, int w) {
e[++ edgeCnt] = (edge) {x, y, w, ls[x]}; ls[x] = edgeCnt;
e[++ edgeCnt] = (edge) {y, x, w, ls[y]}; ls[y] = edgeCnt;
}
inline void swap(int &x, int &y) {
x ^= y;
y ^= x;
x ^= y;
}
inline int getFather(int now) {
return ((now == fa[now])?(now):(fa[now] = getFather(fa[now])));
}
inline int getDis(int x, int y) {
return dis[x] ^ dis[y];
}
inline void dfs(int f, int now) {
used[now] = 1;
erg(i, now) {
if (e[i].y == f) {
continue;
}
dis[e[i].y] = dis[now] ^ e[i].w;
dfs(now, e[i].y);
}
}
int main(void) {
int n = read() + 1;
int m = read();
int czy = read();
int lastAns = 0;
rep(i, 1, n) {
fa[i] = i;
size[i] = 1;
}
while (m --) {
int l = read() ^ (czy * lastAns);
int r = read() ^ (czy * lastAns);
int k = read() ^ (czy * lastAns);
r += 1;
int fl = getFather(l);
int fr = getFather(r);
if (fl == fr) {
lastAns = (k == getDis(l, r));
} else {
addEdge(l, r, k);
if (size[fl] < size[fr]) {
swap(l, r);
swap(fl, fr);
}
size[fl] += size[fr];
dis[r] = dis[l] ^ k;
dfs(l, r);
fa[fr] = fl;
lastAns = 1;
}
writeln(lastAns);
}
fill(used, 0);
rep(i, 1, n) {
if (!used[i]) {
dis[i] = dis[i - 1];
dfs(0, i);
}
}
rep(i, 2, n) {
int prt = getDis(i, i - 1);
writeln(prt);
}
return 0;
}