Portal --> agc016D

Description

​  一个序列,一次操作将某个位置变成整个序列的异或和,现在给定一个目标序列,问最少几步可以得到目标序列

​  

Solution

​  翀哥神仙!(守恒什么的哈哈哈哈哈哈哈==)

​​  首先当然是要快乐手玩样例啊然后就发现这个异或是假的,比如说手头上有四个元素\(\{a,b,c,d\}\),比如说我们现在用异或和替掉\(b\)(用\(\oplus\)表示异或),那就是\(\{a,a\oplus b\oplus c\oplus d,c,d\}\),然后这个时候我们再用异或和替换掉\(a\),那么我们就得到了\(\{b,a\oplus b\oplus c\oplus d,c,d\}\),类似地,我们下一步对哪个位置操作,那个位置就会变成\(a\),(具体为什么的话就是因为。。异或同一个数两次影响会抵消)所以实际上我们这个异或操作就是一个换位操作

​  然后我们来判一下无解的情况:注意到因为这个操作其实是一个换位操作,所以目标序列中的组成元素如果与原序列中的组成元素,要么都相同,要么只能差一个,并且这差的一个必须是原序列中所有数的异或和(因为你不可能搞出其他新的元素了)

​​  在实现上我们可以将两个序列的异或和(目标序列的异或和必定是缺的那个数具体为什么的话。。手玩一下就比较清晰了)也当做一个元素丢进序列末尾,对两个序列分别排序之后,如果说有一个位置元素不相同那就凉凉

​  

​  接下来看有解的情况,如何保证操作次数最小

​  首先对于那些两个序列中值相等的位置,不操作是最优的,那么接下来只考虑那些不相等的位置

​​  重新看一下上面手玩的那个过程,我们可以直观一点把它想象成:你从序列里面拿出来一个数,然后用异或和填上它的空缺,然后你开始拿这个数去换别的数,交换的具体过程就是你把另一个数从它的位置上面拿出来,然后把手头上这个数放到那个位置上,再拿这个新换来的数去继续交换,直到换到目标序列

​  因为要让交换的次数最小,我们希望每次交换都能满足一个位置的目标要求,再具体一点就是每一步我们都希望将手头上拿的着的数放到它的目标位置,那么考虑这样一种建图方式:将相同的值(包括两个序列的异或和)看成一个点,对于每个位置\(x\)(我们只考虑那些值不相等的位置),原序列中的值向目标序列中的值连一条边(对于原序列的异或和的话,我们也是正常连就好了),我们的交换要从原序列的异或和开始,沿着边走,把所有的边都走一遍(一条边代表一次操作)

​​  那所以我们现在得到了一个有若干个连通块的图,而每一个连通块其实应该是一个环,因为考虑每个点的入度和出度,如果说一个值在原序列中出现过,那么必定有\(1\)的出度,而如果一个值在目标序列中出现过,必定有\(1\)的入度,由于原序列和目标序列的组成元素相同,所以每个元素都有\(1\)的入度和\(1\)的出度,所以必定每个连通块都是一个环

​​  那么现在记不相等的位置数量为\(m\),我们手头上的图总共有\(m+1\)条边(还有一条异或和连出来的边),我们要从原序列异或和对应的点开始把每条边走一遍,遍历一条边需要\(1\)的代价,从一个环跳到另一个环的话也是需要\(1\)的代价(要先拿一个出来才能开始新的交换),那么总的代价就是\(m+\)环数\(-1\),并且,如果说异或和所处的是一个大小为\(1\)的连通块,那么一开始还需要跳出来,所以这种情况下答案还要再\(+1\)

​  

​​  代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int a[N],b[N],a1[N],b1[N],f[N],sz[N];
int n,m,xsuma,xsumb,Cnt,ans;
void prework(){
a1[0]=unique(a1+1,a1+1+n)-a1-1;
for (int i=1;i<=n;++i){
a[i]=lower_bound(a1+1,a1+1+a1[0],a[i])-a1;
b[i]=lower_bound(a1+1,a1+1+a1[0],b[i])-a1;
}
for (int i=1;i<=a1[0];++i) f[i]=i,sz[i]=1;
}
int get_f(int x){return f[x]=f[x]==x?x:get_f(f[x]);}
void link(int x,int y){
get_f(x); get_f(y);
if (f[x]==f[y]) return;
sz[f[y]]+=sz[f[x]];
f[f[x]]=f[y];
}
void solve(){
for (int i=1;i<=n;++i){
if (a[i]==b[i]&&i!=n) continue;
ans+=(i<n);
link(a[i],b[i]);
}
if (f[a[n]]==a[n]&&sz[a[n]]==1) ++ans;
for (int i=1;i<=a1[0];++i)
if (f[i]==i&&sz[i]>1)
++ans;
} int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int tmp;
bool flag=true;
scanf("%d",&n);
xsuma=0; xsumb=0;
for (int i=1;i<=n;++i) scanf("%d",a+i),a1[i]=a[i],xsuma^=a[i];
for (int i=1;i<=n;++i) scanf("%d",b+i),b1[i]=b[i],xsumb^=b[i];
a[++n]=a1[n]=xsuma;
b[n]=b1[n]=xsumb;
sort(a1+1,a1+1+n);
sort(b1+1,b1+1+n);
for (int i=1;i<=n;++i)
if (a1[i]!=b1[i]){printf("-1\n"); return 0;}
Cnt=0;
for (int i=1;i<=n;++i)
if (a[i]!=b[i]) ++Cnt;
if (Cnt==0){
printf("0\n"); return 0;
}
prework();
solve();
printf("%d\n",ans-1);
}

【agc016D】XOR Replace的更多相关文章

  1. 【BZOJ2337】Xor和路径(高斯消元)

    [BZOJ2337]Xor和路径(高斯消元) 题面 BZOJ 题解 我应该多学点套路: 对于xor之类的位运算,要想到每一位拆开算贡献 所以,对于每一位拆开来看 好了,既然是按位来算 我们就只需要计算 ...

  2. 【BZOJ2115】Xor(线性基)

    [BZOJ2115]Xor(线性基) 题面 BZOJ Description Input 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si ...

  3. 【Go】strings.Replace 与 bytes.Replace 调优

    原文链接:https://blog.thinkeridea.com/201902/go/replcae_you_hua.html 标准库中函数大多数情况下更通用,性能并非最好的,还是不能过于迷信标准库 ...

  4. 【HDU3949】XOR

    [题目大意] 给定一个数组,求这些数组通过异或能得到的数中的第k小是多少. 传送门:http://vjudge.net/problem/HDU-3949 [题解] 首先高斯消元求出线性基,然后将k按照 ...

  5. BZOJ 2115 【Wc2011】 Xor

    Description Input 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 ...

  6. 【BZOJ-2115】Xor 线性基 + DFS

    2115: [Wc2011] Xor Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 2142  Solved: 893[Submit][Status] ...

  7. 【bzoj2115】 Xor

    www.lydsy.com/JudgeOnline/problem.php?id=2115 (题目链接) 题意 给出一张图,可能有重边和自环,在图中找出一条从1-n的路径,使得经过的路径的权值的异或和 ...

  8. 【SQLite】使用replace替换字段中的字符

    使用replace替换字段中的字符 如:替换production表中的specification字段中的两个空格为一个空格: update production set specification = ...

  9. 【bzoj2115】【wc2011】Xor

    2115: [Wc2011] Xor Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 5380  Solved: 2249[Submit][Status ...

随机推荐

  1. JavaScript 中函数的参数

    functionName(parameter1, parameter2, parameter3) { // 要执行的代码…… } 参数规则 JavaScript 函数定义时形参没有指定数据类型. Ja ...

  2. Selenium2+python自动化-iframe

    前言 本篇详细讲解iframe的相关切换操作. 一.frame和iframe区别 Frame与Iframe两者可以实现的功能基本相同,不过Iframe比Frame具有更多的灵活性. frame是整个页 ...

  3. python错误记录

    在主函数里调用其他函数时形参顺序要一致 错例如下:

  4. echarts.js使用心得--demo

    首先要感谢一下我的公司,因为公司需求上面的新颖(奇葩)的需求,让我有幸可以学习到一些好玩有趣的前端技术. 废话不多时 , 直接开始. 第一步: 导入echarts.js文件 下载地址:http://e ...

  5. 3.hive的thriftserver服务

    1.ThiftServer介绍 正常的hive仅允许使用HiveQL执行查询.更新等操作,并且该方式比较笨拙单一.幸好Hive提供了轻客户端的实现,通过HiveServer或者HiveServer2, ...

  6. pyextend库-merge可迭代对象合并函数

    pyextend - python extend lib merge (iterable1, *args) 参数:  iterable1: 实现 __iter__的可迭代对象, 如 str, tupl ...

  7. C++ STL中的Binary search(二分查找)

    这篇博客转自爱国师哥,这里给出连接https://www.cnblogs.com/aiguona/p/7281856.html 一.解释 以前遇到二分的题目都是手动实现二分,不得不说错误比较多,关于返 ...

  8. SQLSERVER 根据身份证号码 往出生年月日 赋值

    update CREW_SailorInfo set DT_DOB= ( case then , ) then , ) else null end) 注:此问题仅供参考 如有疑问 请加QQ群18153 ...

  9. JS 操作 checkbox(cc角色管理等)

    1.获取选中的权限的个数 var size=$("input[name='privileges']:checked").size();

  10. Alpha冲刺总结报告

    一.项目预期计划 允许粗糙的美工设计.由于是毫无经验的人生第一次,必定在开发过程中会遇到许多的问题,因而我们必定会花费不少时间在学习和debug上. 实现除了他山之石和规则系统以外的所有内容. 在日历 ...