版权声明:本人所有          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