Codeforces 1044 D. Deduction Queries ——带权并查集+STL

This way

题意:

现在有一个大小为 2 30 2^{30} 230的数组,每个位置都有一个值,每次有两种操作:
1 x y z 表示告诉你x到y区间的所有值异或和为z(如果和之前告诉你的有悖就权当没说)
2 x y 问你区间x到y的所有值的异或和是多少

题解:

和这道题很像啊:This way
如果不是很清楚带权并查集的也可以去瞄一眼,我讲了一点点基础
首先这道题它也是异或,那么就不需要特别的分fax和fay两种合并情况。
然后的话,它这个数组长度很大,就没办法像以前一样直接开一个数组,那么我们就用unordered_map就行了,然后我也懒的搞启发式合并,下次有机会一定。
我一开始是分每一位考虑的,T了之后发现不用那么麻烦,直接将x和y+1连起来,并且更新答案就行了。
#include
using namespace std;
unordered_map<int,int>fa,bit;
int finds(int x){
    if(!fa.count(x))return x;
    int f=fa[x];
    fa[x]=finds(fa[x]);
    bit[x]^=bit[f];
    return fa[x];
}
void merge(int x,int y,int b){
    int fax=finds(x),fay=finds(y);
    if(fax==fay)return ;
    fa[fay]=fax;
    bit[fay]=bit[x]^bit[y]^b;
}
int query(int x,int y){
    int fax=finds(x),fay=finds(y);
    if(fax!=fay)return -1;
    return bit[y]^bit[x];
}
int main()
{
    int n;
    scanf("%d",&n);
    int la=0;
    while(n--){
        int op,x,y,b;
        scanf("%d%d%d",&op,&x,&y);
        x^=la,y^=la;
        if(x>y)swap(x,y);
        y++;
        if(op-2){
            scanf("%d",&b);
            b^=la;
            merge(x,y,b);
        }
        else{
            int ans=query(x,y);
            printf("%d\n",ans);
            la=~ans?ans:1;
        }
    }
    return 0;
}

你可能感兴趣的:(并查集,stl)