Lyft Level 5 Challenge 2018 - Final Round:F. Deduction Queries(带权并查集)

本文介绍了一种使用带权并查集处理区间异或查询的方法,通过对区间进行离散化处理,解决了在大规模数据下快速更新和查询区间内元素异或值的问题。

F. Deduction Queries
time limit per test 2 seconds
memory limit per test 256 megabytes
inputstandard input
outputstandard output

There is an array a of 2 30 2^{30} 230 integers, indexed from 0 to 2 30 − 1 2^{30}−1 2301. Initially, you know that 0 ≤ a i &lt; 2 30 ( 0 ≤ i &lt; 2 30 ) 0≤a_i&lt;2^{30} (0≤i&lt;2^{30}) 0ai<230(0i<230), but you do not know any of the values. Your task is to process queries of two types:

1 l r x: You are informed that the bitwise xor of the subarray [l,r] (ends inclusive) is equal to x. That is, a l ⊕ a l + 1 ⊕ … ⊕ a r − 1 ⊕ a r = x a_l⊕a_{l+1}⊕…⊕a_{r−1}⊕a_r=x alal+1ar1ar=x, where ⊕ is the bitwise xor operator. In some cases, the received update contradicts past updates. In this case, you should ignore the contradicting update (the current update).
2 l r: You are asked to output the bitwise xor of the subarray [l,r] (ends inclusive). If it is still impossible to know this value, considering all past updates, then output −1.
Note that the queries are encoded. That is, you need to write an online solution.

Input
The first line contains a single integer q ( 1 ≤ q ≤ 2 ⋅ 1 0 5 ) q (1≤q≤2⋅10^5) q(1q2105) — the number of queries.

Each of the next q lines describes a query. It contains one integer t ( 1 ≤ t ≤ 2 ) t (1≤t≤2) t(1t2) — the type of query.

The given queries will be encoded in the following way: let last be the answer to the last query of the second type that you have answered (initially, last=0). If the last answer was −1, set last=1.

If t=1, three integers follow, l ′ l^′ l, r ′ r^′ r, and x ′ x^′ x ( 0 ≤ l ′ , r ′ , x ′ &lt; 2 30 ) (0≤l^′,r^′,x^′&lt;2^{30}) (0l,r,x<230), meaning that you got an update. First, do the following:
l = l ′ ⊕ l a s t , r = r ′ ⊕ l a s t , x = x ′ ⊕ l a s t l=l^′⊕last, r=r^′⊕last, x=x^′⊕last l=llast,r=rlast,x=xlast
and, if l &gt; r l&gt;r l>r, swap l and r.

This means you got an update that the bitwise xor of the subarray [l,r] is equal to x (notice that you need to ignore updates that contradict previous updates).

If t=2, two integers follow, l ′ l^′ l and r ′ r^′ r ( 0 ≤ l ′ , r ′ &lt; 2 30 ) (0≤l^′,r^′&lt;2^{30}) (0l,r<230), meaning that you got a query. First, do the following:
l = l ′ ⊕ l a s t , r = r ′ ⊕ l a s t l=l^′⊕last, r=r^′⊕last l=llast,r=rlast
and, if l &gt; r l&gt;r l>r, swap l and r.

For the given query, you need to print the bitwise xor of the subarray [l,r]. If it is impossible to know, print −1. Don’t forget to change the value of last.

It is guaranteed there will be at least one query of the second type.

Output
After every query of the second type, output the bitwise xor of the given subarray or −1 if it is still impossible to know.

Examples
input
12
2 1 2
2 1 1073741822
1 0 3 4
2 0 0
2 3 3
2 0 3
1 6 7 3
2 4 4
1 0 2 1
2 0 0
2 4 4
2 0 0
output
-1
-1
-1
-1
5
-1
6
3
5
input
4
1 5 5 9
1 6 6 5
1 6 5 10
2 6 5
output
12

思路:带权并查集,原题:https://www.nowcoder.com/acm/contest/119/A。
这题只是把数据范围加大了,因为并查集其实和大小没有关联,所以可以把区间离散化。
r [ i ] r[i] r[i]表示区间 ( p [ i ] , i ] (p[i],i] (p[i],i]里所有数的异或值。

#include<bits/stdc++.h>
using namespace std;
const int MAX=4e5+10;
map<int,int>ma;
int p[MAX],r[MAX];
int f(int x)
{
    if(p[x]==x)return x;
    int nex=p[x];
    p[x]=f(p[x]);
    r[x]^=r[nex];
    return p[x];
}
int main()
{
    for(int i=1;i<=4e5;i++)p[i]=i,r[i]=0;
    int T,last=0,cnt=1;
    cin>>T;
    while(T--)
    {
        int op,x,y,z;
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d%d%d",&x,&y,&z);
            x^=last;
            y^=last;
            z^=last;
            if(x>y)swap(x,y);
            x--;        //因为是[x,y]的异或值为z,所以在并查集里面查询合并之前,x--
            if(ma[x]==0)ma[x]=cnt++;
            if(ma[y]==0)ma[y]=cnt++;
            x=ma[x];
            y=ma[y];
            int fx=f(x),fy=f(y);
            if(fx==fy)continue;
            p[fy]=fx;
            r[fy]=r[y]^r[x]^z;
        }
        else
        {
            scanf("%d%d",&x,&y);
            x^=last;
            y^=last;
            if(x>y)swap(x,y);
            x--;
            if(ma[x]==0)ma[x]=cnt++;
            if(ma[y]==0)ma[y]=cnt++;
            x=ma[x];
            y=ma[y];
            int fx=f(x),fy=f(y);
            if(fx==fy)last=r[x]^r[y];
            else last=-1;
            printf("%d\n",last);
        }
        if(last==-1)last=1;
    }
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值