[AGC016D] XOR Replace 题解
题目链接
题目解法
很有思维难度的一道题
首先考虑简化操作(或者说用一种比较好的方法表示)
假设我们选择交换的位置为 ,不难发现,操作等价于交换 和
于是,有解的条件就好判了,即
操作可以理解为路径,即我们将 连边(),需要将每条边的遍历恰好一次(因为这样操作次数最小),
对于连通内的理解是找到一条欧拉路径,根据有解的性质,这个连通块出度和入度的差 ,所以一定有欧拉路径
对于多个连通块,考虑用一条路径将两个连通块串起来
因为对于所有连通块,至多只有一个的出度 入度,且差 ,即说明至多只有一个存在欧拉路径,其他连通块都是存在欧拉回路,这样不难构造出一条合法的路径,使得经过的路径数目为 边数 + 连通块数 - 1
注意特判异或和为孤立点的情况
时间复杂度
#include <bits/stdc++.h> #define F(i,x,y) for(int i=(x);i<=(y);i++) #define DF(i,x,y) for(int i=(x);i>=(y);i--) #define ms(x,y) memset(x,y,sizeof(x)) #define SZ(x) (int)x.size()-1 #define pb push_back using namespace std; typedef long long LL; typedef unsigned long long ull; typedef pair<int,int> pii; template<typename T> void chkmax(T &x,T y){ x=max(x,y);} template<typename T> void chkmin(T &x,T y){ x=min(x,y);} inline int read(){ int FF=0,RR=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1; for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48; return FF*RR; } const int N=200100; int n,a[N],b[N]; map<int,int> mp; bool used[N]; int fa[N],siz[N]; int get_father(int x){ return x==fa[x]?x:fa[x]=get_father(fa[x]);} int main(){ n=read(); int sxor=0; F(i,1,n) a[i]=read(),mp[a[i]]++,sxor^=a[i]; F(i,1,n) b[i]=read(),mp[b[i]]--; mp[sxor]++; for(auto it:mp) if(it.second<0){ puts("-1");exit(0);} int cnt=0; for(auto &it:mp) it.second=++cnt; F(i,1,n) a[i]=mp[a[i]],b[i]=mp[b[i]];sxor=mp[sxor]; F(i,1,cnt) fa[i]=i; int ans=0; F(i,1,n) if(a[i]!=b[i]) fa[get_father(b[i])]=get_father(a[i]),ans++,used[a[i]]=used[b[i]]=true; F(i,1,cnt) if(used[i]) siz[get_father(i)]++; F(i,1,cnt) ans+=siz[i]>0; if(!used[sxor]) ans++; printf("%d\n",max(0,ans-1)); fprintf(stderr,"%d ms\n",int(1e3*clock()/CLOCKS_PER_SEC)); return 0; }
标签:
Atcoder
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通