您的位置:首页 > 其它

POJ 1733 Parity Game

2009-11-20 14:19 232 查看
Parity game

Time Limit: 1000MSMemory Limit: 65536K
Total Submissions: 2426Accepted: 992
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

Source
CEOI
1999

/*
并查集的高级应用
对于每一个输入 p1 p2 b,我们可以这样考虑:
b = (p2 到某个位置之间的1的个数) - (p1 - 1 到同样某个位置之间的1的个数)的奇偶性。这个位置即为
p1 - 1和p2共同的参照位置(并查集的主节点),因此联想到了并查集,并查集的特点就是处理集合之间的所
属关系以及数量关系,具体处理方式是:
1)sets[i].sid表示i位置的参照位置,sets[i].dist表示i位置与sets[i].sid位置之间的1的个数的奇偶性
2)由于输入num的范围非常大,因此利用Map来做哈希
3)奇偶性的处理方式可以用异或来做
*/
#include <iostream>
#include <cstring>
#include <map>
#define MAX_N 10010
using namespace std;
struct seg
{
//rank是秩,用来加速处理速度
int sid, num, rank;
bool dist;
}sets[MAX_N + 1];
int segNum;
char temp[10];
map<int, int> hash;
void swap(int &v1, int &v2)
{
int temp = v1;
v1 = v2;
v2 = temp;
}
//得到num这个数对应的id
int getIndex(int num)
{
map<int, int>::iterator iter;
if((iter = hash.find(num)) != hash.end())
return iter->second;
else return -1;
}
//并查集的find操作
int find(int index)
{
//自身就是当前集合的主节点
if(sets[index].sid == index) return index;
else
{
int pre = sets[index].sid;
//更新主节点
sets[index].sid = find(sets[index].sid);
//更新相对于主节点的dist
sets[index].dist = sets[index].dist ^ sets[pre].dist;
return sets[index].sid;
}
}
//处理输入数据num1 num2 dist
bool joint(int num1, int num2, bool dist)
{
//得到数据在map中对应的Index
int index1 = getIndex(num1), index2 = getIndex(num2);
//找到两个元素的主节点id
int sid1 = find(index1);
int sid2 = find(index2);
//相等的话表面num1, num2早已经处理过了,这时需要核对他们之间的距离是不是dist
if(sid1 == sid2) return ((sets[index1].dist ^ sets[index2].dist) == dist);

//否则对两个集合合并,并更新其中一个集合的主id,这里用到了秩关系来加速处理
if(sets[sid1].rank < sets[sid2].rank)
{
//更新主节点id
sets[sid1].sid = sid2;
//更新距离
sets[sid1].dist = sets[index1].dist ^ sets[index2].dist ^ dist;
}
else
{
sets[sid2].sid = sid1;
sets[sid2].dist = sets[index2].dist ^ sets[index1].dist ^ dist;
if(sets[sid1].rank == sets[sid2].rank)
sets[sid1].rank++;
}
return true;
}
int main()
{
int n, sn, i, f, t;
bool b;
scanf("%d%d", &n, &sn);
segNum = 0;
int endPos = sn;
bool can = true;
memset(sets, 0, sizeof(sets));
for(i = 1; i <= sn; i++)
{
scanf("%d%d%s", &f, &t, temp);
if(f > t) swap(f, t);
int index1 = getIndex(f - 1);
if(index1 == -1)
{
sets[segNum].num = f - 1;
sets[segNum].dist = 0;
sets[segNum].sid = segNum;
hash[f - 1] = segNum;
segNum++;
}
int index2 = getIndex(t);
if(index2 == -1)
{
sets[segNum].num = t;
sets[segNum].dist = 0;
sets[segNum].sid = segNum;
hash[t] = segNum;
segNum++;
}
if(strcmp(temp, "odd") == 0) b = 1;
else b = 0;
if(can)
{
if(!joint(f - 1, t, b))
{
endPos = i - 1;
can = false;
&;nbsp;   }
}
}
printf("%d/n", endPos);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: