首页 > 代码库 > 51nod 1204 Parity(并查集应用)
51nod 1204 Parity(并查集应用)
1204 Parity
题目来源: Ural
基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
你的朋友写下一串包含1和0的串让你猜,你可以从中选择一个连续的子串(例如其中的第3到第5个数字)问他,该子串中包含了奇数个还是偶数个1,他会回答你的问题,然后你可以继续提问......你怀疑朋友的答案可能有错,或说同他之前的答案相互矛盾,例如:1 - 2 奇数,3 - 4 奇数,那么可以确定1 - 4 一定是偶数,如果你的朋友回答是奇数,就产生了矛盾。给出所有你朋友的答案,请你找出第一个出现矛盾的答案。
Input
第1行:2个数N, Q,N为串的长度,Q为询问的数量。(2 <= N <= 100000, 2 <= Q <= 50000)第2 - Q + 1行:每行包括两个数以及一个字符串来描述朋友的回答,2个数中间用空格分隔,分别表示区间的起点和终点,后面的字符为"even"或"odd",表示朋友的答案。
Output
输出1个数,表示朋友的答案中第一个错误答案的位置,如果所有答案均不矛盾,则输出-1。
Input示例
10 51 2 even3 4 odd5 6 even1 6 even7 10 odd
Output示例
4
/*51nod 1204 Parity(并查集应用)problem:你可以从中选择一个连续的01子串,然后是q个询问和回答. 表示区间[l,r]中有奇数或者偶数个1. 求第一个出现矛盾的位置solve:考虑了下线段树什么的,发现并不怎么靠谱. 没做过类似的,完全没想到并查集,卒.....如果[l,r]是even,那么[1,l-1]和[1,r]中1的个数都是偶数 or 奇数.如果[l,r]是odd,那么 [1,l-1] 和 [1,r]的奇偶性不同.就转换成了判断前缀和的问题所以用[1,n]表示‘相同‘关系,[n+1,2*n]虚拟表示‘不同‘关系.建立两个集合判断 (l-1+n,r) && (l-1,b+n) 就能确定 l-1和r是否为‘相同‘关系. 其它同理hhh-2016/09/06-20:47:14*/#pragma comment(linker,"/STACK:124000000,124000000")#include <algorithm>#include <iostream>#include <cstdlib>#include <stdio.h>#include <cstring>#include <vector>#include <math.h>#include <queue>#include <set>#include <map>#define lson i<<1#define rson i<<1|1#define ll long long#define clr(a,b) memset(a,b,sizeof(a))#define scanfi(a) scanf("%d",&a)#define scanfs(a) scanf("%s",a)#define scanfl(a) scanf("%I64d",&a)#define scanfd(a) scanf("%lf",&a)#define key_val ch[ch[root][1]][0]#define eps 1e-7#define inf 0x3f3f3f3f3f3f3f3fusing namespace std;const ll mod = 1000000007;const int maxn = 300050;const double PI = acos(-1.0);const int limit = 33;int pre[maxn];template<class T> void read(T&num){ char CH; bool F=false; for(CH=getchar(); CH<‘0‘||CH>‘9‘; F= CH==‘-‘,CH=getchar()); for(num=0; CH>=‘0‘&&CH<=‘9‘; num=num*10+CH-‘0‘,CH=getchar()); F && (num=-num);}int stk[70], tp;template<class T> inline void print(T p){ if(!p) { puts("0"); return; } while(p) stk[++ tp] = p%10, p/=10; while(tp) putchar(stk[tp--] + ‘0‘); putchar(‘\n‘);}int fin(int x){ if(pre[x ]== x) return x; return pre[x] = fin(pre[x]);}void unio(int a,int b){ int ta= fin(a); int tb = fin(b); pre[ta] = tb;}char op[10];int main(){// freopen("in.txt","r",stdin); int n,q,flag = 0; int a,b; read(n); read(q); for(int i = 0;i <= 2*n;i++) pre[i] = i; for(int i = 1; i <= q; i++) { scanf("%d%d%s",&a,&b,op); if(flag) continue; if(op[0] == ‘e‘) { if(fin(a-1+n) == fin(b) && fin(a-1) == fin(b + n)) { flag = i; } unio(a-1,b); unio(a-1+n,b+n); } else { if(fin(a-1) == fin(b) && fin(a-1+n) == fin(b+n)) { flag = i; } unio(a-1+n,b); unio(a-1,b+n); } } if(flag) printf("%d\n",flag); else printf("-1\n"); return 0;}
51nod 1204 Parity(并查集应用)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。