地址  https://www.acwing.com/problem/content/241/

小A和小B在玩一个游戏。

首先,小A写了一个由0和1组成的序列S,长度为N。

然后,小B向小A提出了M个问题。

在每个问题中,小B指定两个数 l 和 r,小A回答 S[l~r] 中有奇数个1还是偶数个1。

机智的小B发现小A有可能在撒谎。

例如,小A曾经回答过 S[1~3] 中有奇数个1, S[4~6] 中有偶数个1,现在又回答 S[1~6] 中有偶数个1,显然这是自相矛盾的。

请你帮助小B检查这M个答案,并指出在至少多少个回答之后可以确定小A一定在撒谎。

即求出一个最小的k,使得01序列S满足第1~k个回答,但不满足第1~k+1个回答。

输入格式

第一行包含一个整数N,表示01序列长度。

第二行包含一个整数M,表示问题数量。

接下来M行,每行包含一组问答:两个整数l和r,以及回答“even”或“odd”,用以描述S[l~r] 中有奇数个1还是偶数个1。

输出格式

输出一个整数k,表示01序列满足第1~k个回答,但不满足第1~k+1个回答,如果01序列满足所有回答,则输出问题总数量。

数据范围
N≤10^9,M≤
输入样例: even
odd
even
even
odd
输出样例:

解答1:

带权并查集

本题目有两个难点

1 数据范围过大  有 10^9

2 询问的内容如何转化到并查集

问题1 的解决办法是 使用离散化 将不同的数据映射到1 2 3 4。。。,由于只有10000次 询问,每次询问提供两个数据 所以只要提供10000*2的数据范围即可

问题2 的解决办法是 前缀和 如果提供 l和r的范围内1有奇数个还是偶数个 也就是计算 前缀和 sum[r] - sum[l-1]

另由于有偶数减偶数 奇数减奇数 都是偶数   只有两者不同类型分别是奇数偶数中的一种 才会出现最后的差是奇数

那么并查集其实也就是前缀和中每个元素的奇偶性

增加带权数组 所有的前缀和元素都会合并到一个祖先中,d[x]带权数组会记录x元素是否与根是同样的奇偶性

当得到新的询问时候 如果两个元素已经合并在同一个祖先下,那么就可以根据他们与祖先的异同得到他们的异同,再来判断他们与输入的异同是否一致 如果不一致就是发生矛盾,返回即可

代码如下

 #include <iostream>
#include <string>
#include <unordered_map> using namespace std; const int MAX_M = ; int N, M;
int n, m; int fa[MAX_M];
int d[MAX_M]; int idx = ; unordered_map<int, int> S; //离散化
int get(int x) {
if (S.count(x) == ) S[x] = ++idx;
return S[x];
} void init()
{
for (int i = ; i < MAX_M; i++) {
fa[i] = i;
}
} int find(int x) {
if (fa[x] != x) {
int root = find(fa[x]);
d[x] += d[fa[x]]%;
fa[x] = root;
} return fa[x];
} int main()
{ cin >> n >> m;
int res = m;
init();
for (int i = ; i <= m; i++) {
int a, b; string s;
cin >> a >> b >> s;
a = get(a - ); b = get(b);
int pa = find(a), pb = find(b); if (pa == pb) {
//查看两者是否符合之前的信息
if (s == "even")
{
//两者奇偶性相同
if( (d[a] + d[b]) % != ){
//有矛盾
res = i - ;
break;
}
}
else if (s == "odd") {
//两者奇偶性不同
if ((d[a] + d[b]) % != ) {
//有矛盾
res = i - ;
break;
}
}
else {
cout << s << endl;
cout << "error" << endl;
break;
}
}
else {
//pa != pb
//合并
fa[pa] = pb;
int add = ;
if (s == "odd") add = ;
d[pa] = (d[a] + d[b] + add)%;
} }
cout << res << endl; return ;
}

带权并查集

解法2 并查集扩展域

 #include <iostream>
#include <string>
#include <vector>
#include <unordered_map> using namespace std; const int MAX_N = *;
const int Base = MAX_N / ; unordered_map<int, int> S;
int n, m; int p[MAX_N]; int idx = ;
//离散化
int get(int x) {
if (S.count(x) == ) S[x] = ++idx;
return S[x];
} int find(int x)
{
if (x != p[x]) p[x] = find(p[x]); return p[x];
} int main()
{
cin >> n >> m; int res = m;
for (int i = ; i < MAX_N; i++) p[i] = i; for (int i = ; i <= m; i++) {
int a, b; string s;
cin >> a >> b >> s;
a = get(a - ); b = get(b); if (s == "even") {
//相同
if (find(a + Base) == find(b)) {
res = i - ;
break;
}
p[find(a)] = find(b);
p[find(a + Base)] = p[find(b + Base)];
}
else {
if (find(a) == find(b)) {
res = i - ;
break;
}
p[find(a+Base)] = find(b);
p[find(a )] = p[find(b + Base)]; } }
cout << res << endl; return ;
}

扩展域

acwing 239. 奇偶游戏 并查集的更多相关文章

  1. AcWing 239.奇偶游戏 (带权并查集/种类并查集)

    题意:你和朋友玩游戏,有个一\(01\)序列,你每次给出一个区间,朋友会回答这个区间中的\(1\)的个数是奇数还是偶数,但是你亲爱的朋友可能在撒谎,问在哪个询问你能确定你的朋友在撒谎,输出回合数. 题 ...

  2. acwing 1250. 格子游戏 并查集

    地址 https://www.acwing.com/problem/content/1252/ Alice和Bob玩了一个古老的游戏:首先画一个 n×nn×n 的点阵(下图 n=3n=3 ). 接着, ...

  3. AcWing 239. 奇偶游戏

    小A和小B在玩一个游戏. 首先,小A写了一个由0和1组成的序列S,长度为N. 然后,小B向小A提出了M个问题. 在每个问题中,小B指定两个数 l 和 r,小A回答 S[l~r] 中有奇数个1还是偶数个 ...

  4. AcWing:239. 奇偶游戏(前缀和 + 离散化 + 带权并查集 + 异或性质 or 扩展域并查集 + 离散化)

    小A和小B在玩一个游戏. 首先,小A写了一个由0和1组成的序列S,长度为N. 然后,小B向小A提出了M个问题. 在每个问题中,小B指定两个数 l 和 r,小A回答 S[l~r] 中有奇数个1还是偶数个 ...

  5. BZOJ 1854: [Scoi2010]游戏 并查集

    1854: [Scoi2010]游戏 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 2672  Solved: 958[Submit][Status][ ...

  6. 1854: [Scoi2010]游戏[并查集]

    1854: [Scoi2010]游戏 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 4938  Solved: 1948[Submit][Status] ...

  7. 洛谷 P1640 SCOI2010 连续攻击游戏 并查集

    题目描述 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备 ...

  8. bzoj 1854: [Scoi2010]游戏 (并查集||二分图最大匹配)

    链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1854 写法1: 二分图最大匹配 思路:  将武器的属性对武器编号建边,因为只有10000种 ...

  9. 【bzoj1854】[Scoi2010]游戏 - 并查集

    lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备最多只能使 ...

随机推荐

  1. POJ-3026_Borg Maze

    Borg Maze Time Limit: 1000MS Memory Limit: 65536K Description The Borg is an immensely powerful race ...

  2. C#中的字段,常量,属性与方法

    以前是学C++的,初次学微软的C#头都大了.什么字段,常量,属性,方法......微软把别人的东西拿来糅合在C#里,弄成了一个“大杂烩”.其实,说到底,“字段”不就是“变量”吗,所谓的“方法”不就是“ ...

  3. Python从文件中读取内容,包含中文和英文

    读取文件内容使要和保存文件时的格式一致 以UTF-8格式保存文件,如: 读取: 在.py起始行写入:#-*- coding:utf-8 -*- filename = raw_input(u" ...

  4. DataTable CAST 成集合后,进行自定义排序再转换回DataTable

    dt = dt.Rows.Cast<DataRow>().OrderBy(r => Convert.ToInt32(r["数量"])==0?1:0).ThenBy ...

  5. linux 端口映射设置

    iptables -t nat -A PREROUTING -p tcp --dport 新端口 -j REDIRECT --to-ports 旧端口

  6. npm基础用法

    一. 安装 npm基于nodejs,因此应该先安装nodejs 可在nodejs官网中下载安装 我们一般选择安装稳定版,即长期支持版 安装过程很简单,和普通的软件一样,一直 下一步 就好了 nodej ...

  7. H3C SSH配置例子

  8. winform(C#)里弹出“确定”“取消”对话框

    //消息框中需要显示哪些按钮,此处显示“确定”和“取消” MessageBoxButtons messButton = MessageBoxButtons.OKCancel; //"确定要退 ...

  9. SpringBoot使用logback输出日志并打印sql信息 --经典---

    最近在学习springboot以及一些springcloud插件的使用,其中发现默认的配置并不能打印一些有用的日志,所以需要自定义一些日志输出方式以便于查看日志排查问题,目前只整理了两种使用方式,如下 ...

  10. Python--day71--Cookie和Session

    一.Cookie Cookie图示: 二.Session 引用:http://www.cnblogs.com/liwenzhou/p/8343243.html cookie Cookie的由来 大家都 ...