Ural 1003(带权并查集,离散化)
2015-01-31 00:59:37
思路:一道经典的带权并查集。
可能比较难想到用带全并查集做... 但是如果我们定义sum[i]为前i个点中1的个数,那么每个区间[a,b]中1的个数的奇偶性就可用sum[b] - sum[a - 1]的奇偶性表示。
又由于只用考虑奇偶性,因此我们不妨让sum[i]仅记录1的个数的奇偶性,考虑把每个sum[i]看做点,这样点与点之间就满足一种向量加减关系,用带权并查集处理。
重点:每个节点的rank值表示自己与当前根的关系,0表示奇偶性相同,1表示奇偶性不同。
注意点:(1)Find函数中,为了防止因路径压缩而造成的fa[x]改变,要先存下fa[x]的值
(2)main函数中合并完,还要处理Rank值的变化。如fa[y] = x之后,y不再是根,而成为x的子节点,所以其Rank[y]要相应改变。
(3)由于数据范围大,要先进行离散化~
(4)Rank值的变化当然可以用更加方便的“^”异或来搞定....
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <string> 11 #include <iostream> 12 #include <algorithm> 13 using namespace std; 14 15 #define MEM(a,b) memset(a,b,sizeof(a)) 16 #define REP(i,n) for(int i=1;i<=(n);++i) 17 #define REV(i,n) for(int i=(n);i>=1;--i) 18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i) 20 #define MP(a,b) make_pair(a,b) 21 22 typedef long long ll; 23 typedef pair<int,int> pii; 24 const int INF = (1 << 30) - 1; 25 const int MAXN = 10010; 26 27 int L,N,ans; 28 int fa[MAXN],Rank[MAXN]; 29 int sta[MAXN][3]; 30 int tx[MAXN]; 31 32 int Find(int x){ 33 if(fa[x] == x) return x; 34 int tmp = fa[x]; 35 fa[x] = Find(fa[x]); 36 Rank[x] = (Rank[x] + Rank[tmp]) % 2; 37 return fa[x]; 38 } 39 40 void Init(){ 41 FOR(i,0,10000) fa[i] = i; 42 MEM(Rank,0); 43 } 44 45 int main(){ 46 int a,b; 47 char s[10]; 48 while(scanf("%d",&L) != EOF){ 49 if(L == -1) break; 50 Init(); 51 scanf("%d",&N); 52 int ans = N,cnt = 0; 53 REP(i,N){ 54 scanf("%d%d%s",&sta[i][0],&sta[i][1],s); 55 int v = (s[0] == 'e') ? 0 : 1; 56 sta[i][2] = v; 57 tx[++cnt] = sta[i][0]; 58 tx[++cnt] = sta[i][1]; 59 } 60 sort(tx + 1,tx + cnt + 1); 61 int sz = unique(tx + 1,tx + cnt + 1) - tx; 62 REP(i,N){ 63 sta[i][0] = lower_bound(tx + 1,tx + sz + 1,sta[i][0]) - tx; 64 sta[i][1] = lower_bound(tx + 1,tx + sz + 1,sta[i][1]) - tx; 65 } 66 REP(i,N){ 67 a = sta[i][0]; 68 b = sta[i][1]; 69 int v = sta[i][2]; 70 if(ans != N) 71 continue; 72 a--; 73 int x = Find(a),y = Find(b); 74 if(x == y){ 75 if(Rank[a] ^ Rank[b] ^ v) 76 ans = i - 1; 77 } 78 else{ 79 fa[y] = x; 80 Rank[y] = (Rank[a] + Rank[b] + v) % 2; 81 } 82 } 83 printf("%d\n",ans); 84 } 85 return 0; 86 }