[乱搞]JZOJ 5910 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

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

分析

我们根据提示发现,其实序列有n+1个元素,多出来那一个就是异或和

那么问题转换为怎么将序列经过抽出塞入变成目标序列

然后我们将初始序列和目标序列中同位不同的连边,然后看一下有多少联通块即可

但是如果异或和没有用到,也要+1,因为需要先把异或和放进去从而取出来一个数

答案等于联通块大小+联通块个数-1

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <memory.h>
using namespace std;
const int N=1e5+10;
map<int,int> p;
vector<int> l[N];
int a[N],b[N],c[N],d[N];
int n,lsh,ans;
bool vis[N];

void Dfs(int u) {
    vis[u]=1;
    int sz=l[u].size();
    for (int i=0;i<sz;i++)
        if (!vis[l[u][i]])Dfs(l[u][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],!p[a[i]]?p[a[i]]=++lsh:i=i;
    if (!p[a[n+1]]) p[a[n+1]]=++lsh;
    for (int i=1;i<=n;i++) scanf("%d",&b[i]),b[n+1]^=b[i],!p[b[i]]?p[b[i]]=++lsh:i=i;
    if (!p[b[n+1]]) p[b[n+1]]=++lsh;
    memcpy(c,a,sizeof a);memcpy(d,b,sizeof b);
    sort(a+1,a+n+2);sort(b+1,b+n+2);
    for (int i=1;i<=n;i++)
        if (a[i]!=b[i]) {
            printf("-1");
            return 0;
        }
    for (int i=1;i<=n;i++)
        if (c[i]!=d[i])
            l[p[c[i]]].push_back(p[d[i]]),ans++;
    if (c[n+1]!=d[n+1]) l[p[c[n+1]]].push_back(p[d[n+1]]);
    for (int i=1;i<lsh;i++)
        if (l[i].size()&&!vis[i])
            Dfs(i),ans++;
    if (!vis[lsh]) ans++;
    ans--;
    printf("%d",ans);
}
View Code
在日渐沉没的世界里,我发现了你。
原文地址:https://www.cnblogs.com/mastervan/p/9818554.html