Parity Game

总时间限制: 

10000ms

单个测试点时间限制: 

1000ms

内存限制: 

65536kB

描述

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.   

输入

The first line of input file PARITY.IN 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).

输出

There is only one line in output file PARITY.OUT 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.

样例输入

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

样例输出

3

来源

CEOI 1999

机翻:

描述

你不时和你的朋友玩下面的游戏。你的朋友写下一个由 0 和 1 组成的序列。你选择一个连续的子序列(例如从第三位到第五位的子序列),然后问他这个子序列是偶数还是奇数。你的朋友回答了你的问题,你可以向他询问另一个子序列等等。你的任务是猜测整个数字序列。你怀疑你朋友的一些答案可能不正确,你想定罪他说谎。因此,您决定编写一个程序来帮助您解决这个问题。该程序将收到您的一系列问题以及您从朋友那里得到的答案。该程序的目的是找到第一个可证明是错误的答案,即   

输入

输入文件 PARITY.IN 的第一行包含一个数字,它是 0 和 1 序列的长度。这个长度小于或等于1000000000。在第二行,有一个正整数,表示问题的数量和回答的数量。问题和答案的数量小于或等于 5000。其余行指定问题和答案。每行包含一个问题和该问题的答案:两个整数(
所选子序列中第一个和最后一个数字的位置)和一个“偶数”或“奇数”的单词(答案,即所选子序列中 1 的数量,其中“偶数”表示偶数,“奇数”表示奇数)。

输出

输出文件 PARITY.OUT 中只有一行包含一个整数 X。数字 X 表示存在满足第一个 X 奇偶校验条件的 0 和 1 序列,但不存在满足 X+1 条件的序列。如果存在满足所有给定条件的 0 和 1 序列,则数字 X 应该是所有问题的数量。

说明:其实是查并集,从x到y+1(不包括)的位置上有奇数个/偶数个,奇数为1,偶数为0

发现矛盾即可

数据不大可以不压缩路径

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<memory.h>
#include<map>
using namespace std;
struct group {
	int loc;
	int rel;
	group() {};
	group(int x, int y) :loc(x), rel(y) {};
};
map<int, group> line;
/*find(x) x.loc 指向root x.rel 说明与root关系*/
group find(int x) {

	if (line[x].loc != x) {
		group tmp = find(line[x].loc);
		line[x].loc = tmp.loc, line[x].rel = (tmp.rel + line[x].rel) % 2;
	}
	return line[x];
}
int main() {
	int n, k;
	cin >> n >> k;
	int x, y;
	string s;
	int flag = 1;
	group rx, ry;
	for (int i = 1; i <= k; i++) {
		cin >> x >> y >> s;
		y++;
		if (!flag)continue;
		if (line.find(x) == line.end()) {
			if (line.find(y) != line.end()) {//x out y in
				ry = find(y);
				if (ry.loc > x) {
					line[ry.loc] = group(x, (ry.rel + (s == "odd")) % 2);
					line[x] = group(x, 0);
				}
				else
					line[x] = group(ry.loc, (ry.rel + (s == "odd")) % 2);
			}
			else {//x y out
				line[x] = group(x, 0);
				line[y] = group(x, (s == "odd"));
			}
		}
		else {
			if (line.find(y) == line.end()) {
				//x in y out OK 
				line[y] = group(x, (s == "odd"));
			}
			else {//both in
				rx = find(x), ry = find(y);
				if (rx.loc == ry.loc) {
					if (((s == "even") && (!((rx.rel + ry.rel) % 2))) 
						|| ((s == "odd") && ((rx.rel + ry.rel) % 2)))
						continue;
					else {
						cout << i - 1;
						flag = 0;
					}
				}
				else {
					if (ry.loc > rx.loc) {
						line[ry.loc].loc = rx.loc;
						line[ry.loc].rel = ((s == "odd") + rx.rel + ry.rel) % 2;
					}
					else {
						line[rx.loc].loc = ry.loc;
						line[rx.loc].rel = ((s == "odd") + rx.rel + ry.rel) % 2;
					}
				}
			}
		}
	}
	if (flag)cout << k;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值