您的位置:首页 > 其它

AtCoder Grand Contest 016 D - XOR Replace

2018-02-28 21:10 489 查看

Time limit : 2sec / Memory limit : 256MB

Score : 1000 points

Problem Statement

There is a sequence of length N: a=(a1,a2,…,aN). Here, each ai is a non-negative integer.

Snuke can repeatedly perform the following operation:

Let the XOR of all the elements in a be x. Select an integer i (1≤i≤N) and replace ai with x.

Snuke’s objective is to match a with another sequence b=(b1,b2,…,bN). Here, each bi is a non-negative integer.

Determine whether the objective is achievable, and find the minimum necessary number of operations if the answer is positive.

Constraints

2≤N≤105

ai and bi are integers.

0≤ai,bi<230

Input

Input is given from Standard Input in the following format:

N

a1 a2 … aN

b1 b2 … bN

Output

If the objective is achievable, print the minimum necessary number of operations. Otherwise, print -1 instead.

Sample Input 1

3

0 1 2

3 1 0

Sample Output 1

2

At first, the XOR of all the elements of a is 3. If we replace a1 with 3, a becomes (3,1,2).

Now, the XOR of all the elements of a is 0. If we replace a3 with 0, a becomes (3,1,0), which matches b.

Sample Input 2

Copy

3

0 1 2

0 1 2

Sample Output 2

0

Sample Input 3

2

1 1

0 0

Sample Output 3

-1

Sample Input 4

4

0 1 2 3

1 0 3 2

Sample Output 4

5

Gist

给你两个序列 a 和序列 b ,长度各为 N 。

要求最少的变换操作数,使得将序列 a 变为序列 b 。

操作:令 x=序列 a 每个元素的异或和,并用 x 代替一个 ai 。

数据范围:2≤N≤105 , 0≤ai,bi<230

Solution

要会做这题,就必须发现其操作的本质。

发现除了第一次求异或和产生的数是新数外,之后的数都是旧的(替换的)。

因为替换后的异或和就是被替换的数本身(异或的性质)。

那么为了方便处理,就将第一次的新数放到那 N 个数的末尾,

操作就相当于将最后一个数与前面 N 个数中的某个数交换。

不合法的情况就是将两列数排序后不完全相同(无论如何都不能换到相同)。

之后某个位置上 a 要换成 b ,就 a 向b 连一条边,

每个连通块就需要 Size+1 次交换操作(除非包含第 N+1 个数,可以少一次,即答案减一)。

用一个并查集维护即可,注意存数判断时要用 Hash 表。

时间复杂度 O(N log N) 。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
const int N=1e5+5,M=N*100+7;
int tot,ans;
int a
,b
,a1
,b1
;
int f
,bel[M],h[M];
inline int read()
{
int X=0,w=0; char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
inline int get(int x)
{
return f[x]==x?x:f[x]=get(f[x]);
}
inline int hash(int x)
{
int y=x%M;
while(h[y]>=0 && h[y]!=x) y=(y+1)%M;
return y;
}
int main()
{
int n=read();
for(int i=1;i<=n;i++)
{
a[i]=a1[i]=read();
a[n+1]^=a[i];
}
a1[n+1]=a[n+1];
for(int i=1;i<=n;i++)
{
b[i]=b1[i]=read();
b[n+1]^=b[i];
}
b1[n+1]=b[n+1],n++;
sort(a1+1,a1+1+n);
sort(b1+1,b1+1+n);
for(int i=1;i<=n;i++)
if(a1[i]^b1[i]) return 0&printf("-1");
memset(h,-1,sizeof(h));
for(int i=1;i<=n;i++)
if(i==n || a[i]^b[i])
{
if(i<n) ans++;
int k=hash(a[i]);
if(h[k]<0) h[k]=a[i],bel[k]=++tot;
k=hash(b[i]);
if(h[k]<0) h[k]=b[i],bel[k]=++tot;
}
for(int i=1;i<=tot;i++) f[i]=i;
for(int i=1;i<=n;i++)
if(a[i]^b[i]) f[get(bel[hash(a[i])])]=get(bel[hash(b[i])]);
for(int i=1;i<=tot;i++)
if(f[i]==i) ans++;
printf("%d",ans-1);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: