(图论思维题)[agc016_d]XOR Replace

HZOJ
洛谷

写在前面

세상의 모서리, 世界的四方棱角,

구부정하게 커버린,
以微驼伛偻的姿态 成长起来的,

골칫거리 outsider,
令人伤脑筋 不入流的人,

걸음걸이, 옷차림,
步调仪态 衣裳穿着,

이어폰 너머 play list,
耳机另一端 所播放的列表,

음악까지 다 minor,
就连音乐 也都是小众曲目,

넌 모르지,
你并不知晓吧,

떨군 고개 위,
耷拉的脑袋上方,

환한 빛 조명이,
明亮灿烂的灯火,

어딜 비추는지,
是在朝何处照耀,

느려도 좋으니,
就算有些迟缓也无妨,

결국 알게 되길,
希望你终能了然于心,

The one and only,
如此独一无二的你,

You are my celebrity,
在我看来 你就是耀眼名人,

잊지마 넌 흐린 어둠 사이,
请不要忘却 你在朦胧黑暗间,

왼손으로 그린 별 하나,
用左手所勾勒的那颗星星,

보이니 그 유일함이 얼마나,
你可有看见吗 那份唯一,

아름다운지 말야,
是有多么美不堪言,

You are my celebrity,
在我看来 你就是耀眼巨星,

celebrity,
You are my celebrity,
在我看来 你就是耀眼巨星,

지쳐버린 표정 마치,
疲惫不堪的表情,

전원을 꺼놓은 듯이,
就好似已关掉电源般,

심장소린 too quiet,
心跳声 实在太过安静,

니가 가진 반짝거림,
你所拥有的闪光之处,

상상력, identity,
想象力 以及你本身,

까지 모조리 diet,
所有一切 都被扼制压抑,

넌 모르지,
你未曾得知吧,

아직 못다 핀,
为还没完全盛放的你

널 위해 쓰여진,
而提笔撰写创作的,

오래된 사랑시,
古老的爱之诗歌

헤매도 좋으니,
就算稍作彷徨也无妨,

웃음 짓게 되길,
唯愿能令你绽放笑颜,

The one and only,
如此独一无二的你,

You are my celebrity,
在我看来 你就是耀眼名人,

잊지마 넌 흐린 어둠 사이,
请不要忘却 你在浑浊黑暗间,

왼손으로 그린 별 하나,
用左手所绘出的那颗星星,

보이니 그 유일함이 얼마나,
你可有看见吗 那份唯一,

아름다운지 말야,
是有多么无与伦比,

You are my celebrity,
在我看来 你就是耀眼巨星,

발자국마다 이어진 별자리,
伴随每一步 逐渐连接完整的星座,

그 서투른 걸음이 새겨놓은 밑그림,
那笨拙的步伐 所镌刻而下的草图,

오롯이 너를 만나러 가는 길,
为去与你相见 而孤寂前行之路,

그리로 가면 돼 점선을 따라,
只需沿着虚线 朝那里走去即可,

잊지마 이 오랜 겨울 사이,
请不要遗忘 在这漫长冬季间,

언 틈으로 피울 꽃 하나,
从冰缝之隙 绽放的一朵花,

보이니 하루 뒤 봄이 얼마나,
你可有看见吗 一日后的暖春,

아름다울지 말야,
是有多么美不堪言,

You are my celebrity,
在我看来 你就是耀眼巨星,

celebrity,
You are my celebrity,
你是我眼中 最闪闪发光的所在。

[agc016_d]XOR Replace 题解

题意

给定一个序列,每次操作可以将整个序列的异或和与序列中的任一元素交换,求问经过若干次操作后能否到达目标状态,若可以则输出最小操作次数,否则输出-1。

思路

既然在图论的专题里,就要往图上面想了。但是显然没有任何思路。

改变策略,先转换条件。由于异或和具有可逆性,就把问题转化为了初始时给你一个序列外的位置,该位置上的值是序列的异或和,接下来可以将序列上的位置与该位置进行若干次交换,求最小交换次数。

经过转化,判是否有解的问题就迎刃而解了。比较好想的方法就是开两个桶,一个记录目标序列元素的出现次数,一个记录现有的元素,如果某种现有元素少于目标元素就无解。

经过题解的点拨,我们发现可以对对应位置元素不同的位置建边,因为这样某些位置可以组成一个含有欧拉回路的连通块,用边数的操作次数就可以调整完。对于不同的连通块间就可以用序列外的位置沟通,总共需要沟通连通块数量减一次。如果初始序列外的位置是孤立点(即目标序列中没有该元素)则还需要初始的一步跳到连通块里边。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
int n,sum,a[maxn],b[maxn],cnt;
unordered_map<int,int> lsh;
vector<int> cun[maxn];
int tona[maxn],tonb[maxn];
int edge,block;
int tot,to[maxn],nxt[maxn],h[maxn];
inline void adde(int x,int y){
	to[++tot]=y;
	nxt[tot]=h[x];
	h[x]=tot;
}
bool vis[maxn];
inline void dfs(int u){
	vis[u]=1;
	for(int i=h[u];i;i=nxt[i]){
		int y=to[i];
		if(!vis[y]) dfs(y);
	}
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		sum^=a[i];
		if(lsh[a[i]]) a[i]=lsh[a[i]],++tona[a[i]];
		else a[i]=lsh[a[i]]=++cnt,++tona[cnt];
	}
	if(lsh[sum]) sum=lsh[sum];
	else sum=lsh[sum]=++cnt;
	for(int i=1;i<=n;i++){
		cin>>b[i];
		if(lsh[b[i]]) b[i]=lsh[b[i]],++tonb[b[i]];
		else b[i]=lsh[b[i]]=++cnt,++tonb[cnt];
	}
	for(int i=1;i<=cnt;i++)
	  if(tonb[i]>tona[i]+(sum==i)) cout<<-1,exit(0);
	for(int i=1;i<=n;i++)
		if(a[i]!=b[i]) adde(b[i],a[i]),adde(a[i],b[i]),++edge;
	for(int i=1;i<=n;i++)
		if(!vis[b[i]]&&h[b[i]]) block++,dfs(b[i]);
	if(h[sum]) block--;
	cout<<block+edge;
	return 0;
}
posted @ 2025-08-27 22:01  _dlwlrma  阅读(14)  评论(3)    收藏  举报