題目
分析
我們發現,如果[l,r]的異或和爲k是真要求,有且僅當不存在[l,i]和[i,r]兩個區間的異或和不爲k。
我們用帶權並查集了維護這些,但是,由於區間不連續,我們將點權移到邊上,對於區間[l,r]的點權異或和,變成[l,r+1]邊權異或和。並查集合並時將大點連向小點,
最後通過並查集求異或點綴和,如果某個點沒有限制,值爲零。
#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
const int maxlongint=2147483647;
const int mo=1e9+7;
const int N=200005;
using namespace std;
int b[N*2][3],fa[N],v[N],n,m,czy,ans,tot,sum[N],la[N*2],ne[N*2],vv[N*2],to[N*2];
int get(int x)
{
if(x==fa[x]) return x;
int y=get(fa[x]);
v[x]^=v[fa[x]];
return fa[x]=y;
}
int main()
{
freopen("sanae.in","r",stdin);
//freopen("sanae.out","w",stdout);
scanf("%d%d%d",&n,&m,&czy);
for(int i=1;i<=n+1;i++) fa[i]=i;
int tot=0;
for(int i=1,x,y,k;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&k);
x^=ans*czy,y^=ans*czy,k^=ans*czy;
int xx=get(x),yy=get(y+1);
if(xx>yy) swap(xx,yy);
if(xx==yy)
{
if((v[x]^v[y+1])!=k) ans=0;
else ans=1;
}
else
{
ans=1;
fa[yy]=xx,v[yy]=k^v[x]^v[y+1];
}
printf("%d\n",ans);
}
for(int i=2;i<=n+1;i++)
{
int j=get(i);
if(i==j) sum[i]=sum[i-1];
else sum[i]=sum[j]^v[i];
if(i!=1) printf("%d\n",sum[i]^sum[i-1]);
}
}