POJ 1733(边带权并查集+离散化)

Parity game

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 15492   Accepted: 5876

Description

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题目:一个长度为n且只由0和1组成的序列。由m个询问,下面m行两个数l,r,和even或者odd表示闭区间l到r有奇数个还是偶数个1.求的一个最小的k,使得这个01序满足在1到k个问题,而不满足1到k+1个问题思路:n很大,m小,先离散化处理,再用带权并查集
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <iomanip>
#include <algorithm>
#include <queue>
#include <stack>
#include <set>
#include <vector>
//const int maxn = 1e5+5;
#define ll long long
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}

#define MAX INT_MAX
#define FOR(i,a,b) for( int i = a;i <= b;++i)
#define bug cout<<"--------------"<<endl
using namespace std;
int n,m,t;
struct node
{
    int l,r;
    int ans; // ans表示第i次询问是奇还是偶
}query[20010];
int tot;
//fa表示并查集- -,d【i】表示x与fa【i】的奇偶性关系
int a[20010],fa[20010],d[20010];
void cinin() //离散化代码
{
    scanf("%d %d",&n,&m);

    FOR(i,1,m)
    {
        char c[20];
        scanf("%d %d %s",&query[i].l,&query[i].r,c);
        a[++tot] = query[i].l;
        a[++tot] = query[i].r;
        if(c[0] == ‘o‘) query[i].ans = 1;
        else query[i].ans = 0;
    }
    sort(a+1,a+1+tot);
    tot = unique(a+1,a+1+tot) - a - 1;
}
int get(int x)
{
    if(x == fa[x]) return fa[x];
    int root = get(fa[x]);
    d[x] ^= d[fa[x]];
    return fa[x] = root;
}
int main()
{

    cinin();
    for(int i=1;i<=tot;i++) fa[i] = i;//注意这里是tot不是n
    for(int i =1;i<=m;i++)
    {
        int x = lower_bound(a+1,a+1+tot,query[i].l-1) - a;//注意区间是0到l-1和区间0到r,左闭右开
        int y = lower_bound(a+1,a+1+tot,query[i].r) - a;
        int fx = get(x) , fy = get(y);
        if(fx == fy)
        {
            if((d[x] ^ d[y]) != query[i].ans)
            {
                cout<<i-1<<endl;
                return 0;
            }
        }
        else
        {
            fa[fx] = fy;
            //a = b ^ c ^ d 等价于 b = a ^ c ^ d
            d[fx] = d[x] ^ d[y] ^ query[i].ans;
        }
    }
    cout<<m<<endl;

}

原文地址:https://www.cnblogs.com/jrfr/p/11403908.html

时间: 2024-10-09 19:46:07

POJ 1733(边带权并查集+离散化)的相关文章

poj 1733 Parity game 并查集 离散化

点击打开链接题目链接 Parity game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6249   Accepted: 2413 Description Now and then you play the following game with your friend. Your friend writes down a sequence consisting of zeroes and ones. You cho

poj 1733(带权并查集)

题意:有n个结点,给出了q个操作,操作是a b string表示结点a到结点b的和是奇数或偶数,输出x(前x个操作都是正确的). 题解:带权并查集经典题,因为结点可能有10,000,000,000个,所以需要离散化,不用的点就不考虑了.因为要a加到b,如果a==b无法找到各自的根节点并判断是否要合并,所以其实是mp[a - 1]到mp[b]并入集合.另外需要注意结点是有顺序的,父亲结点要大于等于子节点,这样判断才不会出错,所以合并时要考虑两个根结点的大小有不同关系式. #include <std

Parity game POJ - 1733 带权并查集

#include<iostream> #include<algorithm> #include<cstdio> using namespace std; const int N=10010<<1; struct node { int l,r,ans; } q[N]; int a[N],fa[N],d[N],n,m,t_n; int get(int x) { if (x==fa[x]) return x; int root=get(fa[x]); d[x]^=

poj 1733带权并查集

L - Parity game Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Description Now and then you play the following game with your friend. Your friend writes down a sequence consisting of zeroes and ones. You ch

poj 2912(带权并查集)

题意:有n个人玩石头剪刀布的游戏,编号从1到n-1,把所有人分成3组,给每个组分配一个手势(石头.剪子.布),每轮挑出两个人出来进行游戏,这n个人里有一个裁判,他的手势是可以变化的.给出了m轮的游戏结果,a < b表示b赢了a,a = b表示a和b出了同样的手势,问能否找到裁判的编号,是在第几轮发现的. 题解:这题和食物链那个经典带权并查集很像,也可以用0表示父与子是同一种手势,用1表示父大于子,用2表示父小于子.因为裁判的编号不能确定,可以采用枚举的方式,先假定一个人是裁判,然后去掉这个人所有

POJ - 1733 Parity game 带权并查集+离散化

题目大意:有10E位数,每位上的数不是1就是0.现在给出第n位到第m位的1的数量的奇偶性,判断所给出的话有几句是对的 解题思路:有10E位数,肯定要离散化处理 因为有可能给出的区间是左端点等于右端点的,所以每次都把左端点的值减去1再进行处理 给出了区间的奇偶性,就要找一下是否和前面的矛盾,如果该区间的左端点的根节点和右端点的根节点是相同的,那么就可以判断是否正确了 如果根节点不同,就进行合并,合并时要注意判断是谁的根节点比较大 #include<cstdio> #include<algo

poj 1182 带权并查集

食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 45303   Accepted: 13213 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同

POJ 1733 Parity game (并查集)

Parity game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6816   Accepted: 2636 Description 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 conti

总结一下我理解的带权并查集

总结一下我理解的带权并查集 与普通并查集的区别:普通的并查集仅仅记录的是集合的关系,这个关系无非是同属一个集合或者是不在一个集合,而带权并查集是记录集合内元素的关系,而这个关系被带上了一个权值表示集合内元素之间关系的区别,例如食物链这道题,权值为0表示和根节点是同类,权值为1表示吃根节点... 用向量法来表示带权并查集 查询是否在同一个集合,或者同一个集合内的元素如何表示他们之间的关系 ??? 每个元素带一个权值用rank表示 如上图,用向量法表示则是a->root+a->b=b->ro