洛谷 P5937 奇偶游戏
闲话
虽然这题好像找不到原题了,但毋庸置疑地说这的确是并查集的好题。
分析
可以先对奇偶区间进行分析,当这个有偶数个 1 时,区间 \(1-(left-1)\) 一定与 区间 \(1-right\) 的奇偶性相同。
上面的图 \(3-4\) 为偶区间,根据分析,\(1-2\) 为奇区间。\(1-4\) 也为奇区间。
但如果填入的是个奇区间,那么 \(1-2\) 为奇区间,而 \(1-4\) 为偶区间。
知道这个性质我们就可以把奇数区间和偶数区间合并在一起,当遇到添加偶区间却遇到奇区间时就找到了矛盾。
我们可以用开二倍空间的数组分别存储奇区间和偶区间,其实分两个也行。
下见代码,注意这些(x-1)之类的都表示的是(1-(x-1))。
#include <bits/stdc++.h> using namespace std; #define ll long long const int N=2e5+100;//俩倍点 int a[N]; int n,q; int fa[N]; int find(int x){ if(x==fa[x]){ return x; } return fa[x]=find(fa[x]); } void merge(int x,int y){ x=find(x); y=find(y); fa[y]=x; } int main(){ ios::sync_with_stdio(false); cin>>n>>q; for(int i=0;i<=N-66;i++){ fa[i]=i; } int cnt=0,ans=-1; while(++cnt){ if(cnt>q){ break; } int x,y; string s; cin>>x>>y>>s; if(s[0]=='e'){ //奇数和偶数会合并 if(find(x-1)==find(y+n)&&find(x-1+n)==find(y)){ ans=cnt; break; } merge(x-1,y);//奇数 merge(x-1+n,y+n);//偶数 } else{ //奇数与奇数,偶数与偶数会合并 if(find(x-1)==find(y)&&find(x-1+n)==find(y+n)){ ans=cnt; break; } merge(x-1,y+n);//偶变奇 merge(x-1+n,y);//奇变偶 } } cout<<ans; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」