思路: 帶權並查集
分析:
1 題目給定n個條件,要我們找到第一個不滿足條件的編號
2 每一個條件給的是區間[l,r]的1的奇偶數,很明顯[l,r]這個區間的1的個數可以由[0,r]-[0,l-1]得來
3 那麼我們利用並查集的思想,rank[x]表示的是x到跟節點這個區間即[x,father[x]]這個區間的1的個數,那麼奇偶性可以由1和0來表示
4 題目還有一個難點就是要離散化,一般的離散化的步驟是排序+去重,然後找的時候利用二分即可
代碼:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int MAXN = 50010; struct Node{ int x; int y; int mark; }; Node node[MAXN]; int arr[MAXN] , pos; int father[MAXN] , rank[MAXN] , num; void init(){ sort(arr , arr+pos); num = unique(arr , arr+pos)-arr; memset(rank , 0 , sizeof(rank)); for(int i = 0 ; i <= num ; i++) father[i] = i; } int find(int x){ if(father[x] != x){ int fa = father[x]; father[x] = find(father[x]); rank[x] = (rank[x]+rank[fa])%2; } return father[x]; } int search(int x){ int left = 0; int right = num-1; while(left <= right){ int mid = (left+right)>>1; if(arr[mid] == x) return mid; else if(arr[mid] < x) left = mid+1; else right = mid-1; } } int solve(int n){ for(int i = 0 ; i < n ; i++){ int x = search(node[i].x)+1; int y = search(node[i].y)+1; int fx = find(x); int fy = find(y); int val = node[i].mark; if(fx == fy){ if((rank[y]-rank[x]+2)%2 != val) return i; } else{ father[fx] = fy; rank[fx] = (val+rank[y]-rank[x]+2)%2; } } return n; } int main(){ int len , n; char str[10]; while(scanf("%d%d" , &len , &n) != EOF){ pos = 0; for(int i = 0 ; i < n ; i++){ scanf("%d %d %s" , &node[i].x , &node[i].y , str); node[i].x--; arr[pos++] = node[i].x; arr[pos++] = node[i].y; if(str[0] == 'e') node[i].mark = 0; else node[i].mark = 1; } init(); printf("%d\n" , solve(n)); } return 0; }