51nod 1204 Parity(并查集应用)

Posted Przz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 5
1 2 even
3 4 odd
5 6 even
1 6 even
7 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 0x3f3f3f3f3f3f3f3f
using 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(并查集应用)的主要内容,如果未能解决你的问题,请参考以下文章

51nod-1366 贫富差距——并查集

51nod 1515 明辨是非 并查集+set维护相等与不等关系

51nod 1515 明辨是非 [并查集+set]

51nod 1276 一个标签是并查集但跟并查集没有关系的3级题

51 nod 1427 文明 (并查集 + 树的直径)

51nod1307(暴力树剖/二分&dfs/并查集)