版权声明:本人所有 https://blog.csdn.net/mxYlulu/article/details/89881514
这里的题目一般都是维护状态,每个集合表示的是一种状态(一般为两个)
题目会询问第一次状态冲突的时候[并查集添加状态的时候发现已有状态并且状态不对]
数据结构K题
K题讲述的是:告诉你n个区间的和的奇偶,判断第一个矛盾的地方。
区间和的奇偶可以转换成可以维护的前缀和之差的奇偶,和为奇,前缀和sum[l-1]和sum[r]一定奇偶不同。
前者奇后者偶,或者反过来。这两种状态我们都添加到并查集里去。
那么怎么表示哪个是奇数呢,0~n为奇数,n+1~2*n+1为偶数。类似于罪犯分配问题。后者做过的前提我还没做出来K题,看到题解才恍然大悟,脑子不行就要靠刷题弥补。
#include<bits/stdc++.h> #define FOR(i,a,b) for(int i=a;i<=b;i++) #define ll long long using namespace std; const int MAXN = 1000050*2; int n,m; int f[MAXN]; struct UnionSet { UnionSet(int n) { for (int i = 0; i <= 2*n+1; i++) { f[i] = i; } } UnionSet(){} void uni(int x, int y) { f[find(x)] = find(y); } bool query(int x, int y) { return find(x) == find(y); } int find(int x) { return f[x] == x ? x : (f[x] = find(f[x])); } } us; int main(){ cin>>n>>m; char ch[10]; us=UnionSet(n); FOR(i,1,m){ int x,y; scanf("%d%d%s",&x,&y,ch); x--; if(ch[0]=='e'){ if(us.query(x,y+n+1)||us.query(x+n+1,y)){ cout<<i-1<<endl; return 0; } us.uni(x,y); us.uni(x+n+1,y+n+1); } else{ if(us.query(x,y)||us.query(x+n+1,y+n+1)){ cout<<i-1<<endl; return 0; } us.uni(x+n+1,y); us.uni(x,y+n+1); } } cout<<"ORZQHQH"<<endl; } 罪犯分配问题
文章来源: https://blog.csdn.net/mxYlulu/article/details/89881514