1. 程式人生 > >【JZOJ A組】DuLiu

【JZOJ A組】DuLiu

Description

     LF是毒瘤出題人中AK IOI2019,不屑於參加NOI的唯一的人。他對人說話,總是滿口垃圾題目者也,教人半懂不懂的。因為他姓李,別人便從QQ群上的“毒瘤李Fee”這半懂不懂的話裡,替他取下一個綽號,叫做李Fee。
    李Fee一到機房,所有做題的人便都看著他笑,有的叫道,“李Fee,你又來出毒瘤題了!”他不回答,對驗題人說,“我又出了兩道題,給我驗驗。”便排出一排毒瘤題。大家又故意的高聲嚷道,“你又暴露奸商本性拿毒瘤題騙錢剝削驗題人了!”李Fee睜大眼睛說,“你怎麼這樣憑空汙人清白……”“什麼清白?我前天親眼見你出了道毒瘤騙錢題,被PTY把std吊著打。” 李Fee便漲紅了臉,額上的青筋條條綻出,爭辯道,“出題人的題不能算騙……毒瘤!……出題人的題,能算毒瘤騙錢題麼?”接連便是難懂的話,什麼“多叉splay隨機點分治”,什麼“樹鏈剖分套分治FFT”之類,引得眾人都鬨笑起來:機房內外充滿了快活的空氣。

雖然他的題十分毒瘤,但他的題還總是有買家。李Fee現在有N道毒瘤題,想將這些題出成一組題來騙大錢。然而顯而易見的是,一組題的毒瘤程度不僅和每道題的毒瘤程度有關,也跟它們的排列順序有關,李Fee需要將它們排列成最毒瘤但又最能騙錢的那個順序。
具體來說,這N道題每題都有一個毒瘤值,它們構成了一個序列。李Fee心目中有一個理想的毒瘤值序列,這個序列並不一定每一題的毒瘤值都是原本N道題中出現的,所以李Fee準備進行一些改動。這些改動體現在毒瘤值上就是將某道題的毒瘤值改為所有題的毒瘤值的二進位制異或值。但是,改動題目是很麻煩的,他想算出最少需要多少次改動才能將原本的毒瘤值序列改成理想的毒瘤值序列,李Fee忙於出毒瘤題,他想請發明O(1/n)演算法用暴力搜過所有毒瘤題的你幫他算出答案。但是他是個奸商,所以他並不打算給你報酬。

Input

第一行1個正整數N,如題目所示。
第二行N個非負整數,表示初始的題目毒瘤值序列
第三行N個非負整數,表示理想的題目毒瘤值序列

Output

單獨一行,一個整數,表示最少需要多少次改動
如果怎麼改動都無法改成理想的毒瘤值序列,說明這組題出的相當失敗,請輸出-1

Sample Input

3
0 1 2
3 1 0

Sample Output

2

樣例解釋:
第一次,整個序列異或為3,把第一個數0換成3,序列變成3,1,2
第二次,整個序列異或為0,把第三個數2換成0,序列變成3,1,0

Data Constraint

對於10%的資料,1<=N<=5
對於30%的資料,1<=N<=10
另有20%的資料,毒瘤值為0或1
對於100%的資料,1<=N<=100000 毒瘤值<2^30

Hint

不要被事物的表面現象所迷惑

思路

事實證明。就算沒有被迷惑,你也做不出來

首先,可以發現如果異或值為x,將a[i]替換成x,則x會變成a[i]
所以,我們可以把已獲知看成一個元素,每次操作就是交換a[n+1]與a[i]的位置
由此想到構圖(將不相等的相連)

可以發現,每一個聯通塊要交換邊數+1次
最後輸出ans-1即可(異或值所在聯通塊不用額外換一次)

程式碼

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm> 
#include<vector>
#include<map>
using namespace std;
const int N=1e5+77;
vector<int>q[N];
map<int,int>d;
bool vis[N];
int n,a[N],b[N],cnt,ans,x[N],y[N];
void dfs(int x)
{
	vis[x]=1;
	for(int i=0; i<q[x].size(); i++) if(!vis[q[x][i]]) dfs(q[x][i]);
}
int main()
{
	freopen("duliu.in","r",stdin),freopen("duliu.out","w",stdout);
	scanf("%d",&n);
	for(int i=1; i<=n; i++)
	{
		scanf("%d",&a[i]),a[n+1]^=a[i];
		if(!d[a[i]]) d[a[i]]=++cnt;
	}
	if(!d[a[n+1]]) d[a[n+1]]=++cnt;
	for(int i=1; i<=n; i++)
	{
		scanf("%d",&b[i]),b[n+1]^=b[i];
		if(!d[b[i]]) d[b[i]]=++cnt;
	}
	if(!d[b[n+1]]) d[b[n+1]]=++cnt;
	for(int i=1; i<=n+1; i++) x[i]=a[i],y[i]=b[i];
	sort(x+1,x+n+2),sort(y+1,y+n+2);
	for(int i=1; i<=n; i++) if(x[i]!=y[i])
	{
		printf("-1"); return 0;
	}
	for(int i=1; i<=n+1; i++) a[i]=d[a[i]],b[i]=d[b[i]];
	for(int i=1; i<=n; i++) if(a[i]!=b[i]) ans++,q[a[i]].push_back(b[i]);
	if(a[n+1]!=b[n+1]) q[a[n+1]].push_back(b[n+1]);
	for(int i=1; i<cnt; i++) if(q[i].size()&&!vis[i]) dfs(i),ans++;
	if(!vis[cnt]) ans++;
	printf("%d",ans-1);
}