POJ 1733 Parity game 区间并查集

Now and then you play the following game with your friend. Your friend writes down a sequence consisting of zeroes and ones. You choose a continuous subsequence (for example the subsequence from the third to the fifth digit inclusively) and ask him, whether this subsequence contains even or odd number of ones. Your friend answers your question and you can ask him about another subsequence and so on. Your task is to guess the entire sequence of numbers.

You suspect some of your friend's answers may not be correct and you want to convict him of falsehood. Thus you have decided to write a program to help you in this matter. The program will receive a series of your questions together with the answers you have received from your friend. The aim of this program is to find the first answer which is provably wrong, i.e. that there exists a sequence satisfying answers to all the previous questions, but no such sequence satisfies this answer.

Input

The first line of input contains one number, which is the length of the sequence of zeroes and ones. This length is less or equal to 1000000000. In the second line, there is one positive integer which is the number of questions asked and answers to them. The number of questions and answers is less or equal to 5000. The remaining lines specify questions and answers. Each line contains one question and the answer to this question: two integers (the position of the first and last digit in the chosen subsequence) and one word which is either `even' or `odd' (the answer, i.e. the parity of the number of ones in the chosen subsequence, where `even' means an even number of ones and `odd' means an odd number).

Output

There is only one line in output containing one integer X. Number X says that there exists a sequence of zeroes and ones satisfying first X parity conditions, but there exists none satisfying X+1 conditions. If there exists a sequence of zeroes and ones satisfying all the given conditions, then number X should be the number of all the questions asked.

Sample Input

10
5
1 2 even
3 4 odd
5 6 even
1 6 even
7 10 odd

Sample Output

3

题意:

两个人正在做游戏, A取出一组序列, 然后说出有奇数个或者偶数个1, 然后另一个人判别说的是不是对的。

输出那个有矛盾-1的序列号, 如果都对了的话, 输出一共有多少编号。

思路:

哇,这题我冥思苦想也没能想到怎么做,没办法,只能是寻求一波题解了。

恩, 这题的区间有10亿这麽大, 开个数组已经是不现实的了, 但是只会执行 最多5000次操作。

所以我们只需要建立一个映射去存这些数就行了, 很神奇吧,我也是这么觉得的。

建立映射的话, 可以用个map。 如果这个元素的话, 就给他赋上一个值, 然后通过这个值来建立并查集。

然后, 还有, 建立并查集的时候, 如何实现两个区间的合并呢, 比如[1,2]与[3,4], 这时我们可以通过将区间的左区间-1为父节点, 这样就可以实现区间的悄无声息的合并了。

并查集的查找和合并都与以前做的题目区别不大, 在这里就不多赘述了, 直接上代码吧。

恩,这个题还让我学到了异或的强大之处。

代码如下:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <map>
using namespace std;
//因为一次查询需要记录两个点嘛,所以需要建5000*2大的数组
const int maxn=10010;
int n,q;
int a[maxn];
int re[maxn];
//建立映射
map<int,int>mapp;
//查找
int finds (int x)
{
    int temp=a[x];
    if(x==a[x])
        return x;
    int par=finds(a[x]);
    re[x]=re[x]^re[temp];
    a[x]=par;
    return par;
}
int main()
{
    while(scanf("%d%d",&n,&q)==2)
    {
        for (int i=0;i<maxn;i++)
         {
            a[i]=i;
            re[i]=0;
         }
        //每次操作不要忘记的清空
        mapp.clear();
        //通过这个变量建立映射
        int total=0;
        int ans=q;
        for (int i=0;i<q;i++)
        {
            int x,y,d;
            char s[15];
            scanf("%d%d%s",&x,&y,s);
            if(x>y)
            swap(x,y);
            if(ans<q)
                continue;
            x--;
            if(s[0]=='e')
                d=0;
            else
                d=1;
            //如果map中没有这个Key,那么就建立这样一个映射.
            if(mapp.find(x)==mapp.end())
                 mapp[x]=total++;
            if(mapp.find(y)==mapp.end())
                 mapp[y]=total++;
            int temp1=finds(mapp[x]);
            int temp2=finds(mapp[y]);
            //判定
            if(temp1==temp2)
            {
                if(re[mapp[x]]^re[mapp[y]]!=d)
                {
                    ans=i;
                }
            }
            //合并两个区间
            else
            {
                a[temp2]=temp1;
                re[temp2]=re[mapp[x]]^d^re[mapp[y]];
            }
        }
        printf("%d\n",ans);
      }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41410799/article/details/81582962