Parity game(带权并查集+离散化)
题目链接 //kuangbin
题意:
现在你和你的朋友正在玩一种游戏。 你的朋友写下一串0和1的序列,然后你选择其中一串子序列(如[3,5])并且问他这个序列是包含奇数个1还是偶数个1(和是奇数还是偶数)。 你可以问你的朋友任意个问题,而你的朋友会回答你的问题。 你的任务是猜出整个朋友的序列。但是,你发现你的朋友告诉你的信息可能有误,所以你想写一个程序来指出他的错误。这个程序应该接受一系列你的问题和答案。程序的目标是找到第一个错误的答案。
思路:
由之前做树状数组的题目经验得到,左区间可以-1,使得连贯起来。
因为1e9很大数组开不下,所以离散化(这一步要在左区间-1的步骤之后)。
带权。
1 #include<iostream> 2 #include<cstdio> 3 #include <cctype> 4 #include<algorithm> 5 #include<cstring> 6 #include<cmath> 7 #include<string> 8 #include<cmath> 9 #include<set> 10 #include<vector> 11 #include<stack> 12 #include<queue> 13 #include<map> 14 using namespace std; 15 #define ll long long 16 #define mem(a,x) memset(a,x,sizeof(a)) 17 #define se second 18 #define fi first 19 const ll mod=998244353; 20 const int INF= 0x3f3f3f3f; 21 const int N=2e5+5; 22 23 int n,m; 24 int f[N]; 25 int book[N]; 26 int sum[N]; 27 vector<int>v; 28 29 struct node 30 { 31 int f,s; 32 }a[N]; 33 string str; 34 35 int getf(int x) 36 { 37 if(x!=f[x]) 38 { 39 int t=f[x]; 40 f[x]=getf(f[x]); 41 sum[x]+=sum[t]; // 其实sum[x]^=sum[t]也行,更快,110ms 42 } 43 return f[x]; 44 } 45 int main() 46 { 47 cin>>n>>m; 48 int ans=0; 49 for(int i=0;i<=N;i++) f[i]=i; 50 51 for(int i=1;i<=m;i++) 52 { 53 scanf("%d%d",&a[i].f,&a[i].s); 54 if(a[i].f>a[i].s) swap(a[i].f,a[i].s); 55 a[i].f--; 56 v.push_back(a[i].f); 57 v.push_back(a[i].s); 58 59 cin>>str; 60 if(str[0]=='o') book[i]=1; 61 else book[i]=0; 62 } 63 sort(v.begin(),v.end()); 64 v.erase(unique(v.begin(),v.end()) , v.end()); 65 66 for(int i=1;i<=m;i++) 67 { 68 a[i].f= lower_bound(v.begin(),v.end(),a[i].f)-v.begin()+1; 69 a[i].s= lower_bound(v.begin(),v.end(),a[i].s)-v.begin()+1; 70 int f1=getf(a[i].f); 71 int f2=getf(a[i].s); 72 if(f1!=f2) 73 { 74 f[f1]=f2; 75 sum[f1]=sum[a[i].s]+book[i]-sum[a[i].f]; //sum[f1]=sum[a[i].s]^book[i]^sum[a[i].f] 76 ans++; 77 } 78 else 79 { 80 if( abs(sum[a[i].f]-sum[a[i].s]) %2 != book[i] ) break; //一定要abs。 81 else ans++; 82 } 83 } 84 cout<<ans<<endl; 85 86 }