当前位置: 首页 > news >正文

每日一题8.23

种类并查集的两道题目

第一个题P5937 [CEOI 1999] Parity Game - 洛谷

Alice 和 Bob 在玩一个游戏:他写一个由 0 和 1 组成的序列。Alice 选其中的一段(比如第 3 位到第 5 位),问他这段里面有奇数个 1 还是偶数个 1。Bob 回答你的问题,然后 Alice 继续问。Alice 要检查 Bob 的答案,指出在 Bob 的第几个回答一定有问题。有问题的意思就是存在一个 01 序列满足这个回答前的所有回答,而且不存在序列满足这个回答前的所有回答及这个回答。

输入格式

第 1 行一个整数 n,是这个 01 序列的长度。

第 2 行一个整数 m,是问题和答案的个数。

第 3 行开始是问题和答案,每行先有两个整数,表示你询问的段的开始位置和结束位置。然后是 Bob 的回答。odd表示有奇数个 1,even 表示有偶数个 1。

输出格式

输出一行,一个数 x,表示存在一个 01 序列满足第 1 到第 x 个回答,但是不存在序列满足第 1 到第 x+1 个回答。如果所有回答都没问题,你就输出所有回答的个数。

输入输出样例

输入 #1复制

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

输出 #1复制

3

说明/提示

对于 100% 的数据,1≤n≤109,m≤5×103。

解决方案

根据前缀和可以分为两种并查集:a和b奇偶性相同和不同。分别分配到1~n和n+1~2n

比如x和y奇偶性相同的话就merge(x,y),merge(x+n,y+n)表示x和y是同一种类(即同奇偶性)

不同的话就merge(x,y+n),merge(x+n,y);表示x和y不是同一种类;

不过这个题还要离散化一下,代码如下:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 40000 + 10;
int fa[N];
struct node
{int x, y;string z;
}a[N];//设置一个结构体a方便离散化
void init()
{for (int i = 1; i <= N; i++)fa[i] = i;
}
int find(int x)
{if (fa[x] == x)return x;return fa[x] = find(fa[x]);
}
void merge(int x, int y)
{int fx = find(x), fy = find(y);if (fx!= fy)fa[fx] = fy;
}//并查集板子
inline void solve()
{int n,m;cin >> n >> m;if (!m){cout << 0 << endl;return;}init();vector<int>v;//储存着所有出现过的数然后离散化for (int i = 1; i <= m; i++){string z;int x, y;cin >> x >> y>> z;a[i] = {x-1, y, z};v.push_back(x-1);v.push_back(y);}sort(v.begin(), v.end());v.erase(unique(v.begin(), v.end()));//去重离散化int len = v.size();//一个种类的大小for (int i = 1; i <= m; i++){int x =lower_bound(v.begin(), v.end(), a[i].x) - v.begin(),y = lower_bound(v.begin(), v.end(), a[i].y) - v.begin();//找到输入的x,y在v中对应的编号char c=a[i].z[0];if (c == 'e')//说明要x和y同一奇偶性{if (find(x) == find(y + len))//如果x和y不是同奇偶性的话,就说明这句话不可能实现{cout<<i-1<<endl;return;}merge(x, y);merge(x+len, y + len);//合并}else//同理{if (find(x) == find(y)){cout << i - 1 << endl;return;}merge(x, y + len);merge(x + len, y);}}cout << m << endl;
}
signed main()
{ios::sync_with_stdio(false);cin.tie(0);int t = 1;//cin >> t;while (t--){solve();}
}

 第二个题:P2024 [NOI2001] 食物链 - 洛谷

题目描述

动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形。A 吃 B,B 吃 C,C 吃 A。

现有 N 个动物,以 1∼N 编号。每个动物都是 A,B,C 中的一种,但是我们并不知道它到底是哪一种。

有人用两种说法对这 N 个动物所构成的食物链关系进行描述:

  • 第一种说法是 1 X Y,表示 X 和 Y 是同类。
  • 第二种说法是2 X Y,表示 X 吃 Y。

此人对 N 个动物,用上述两种说法,一句接一句地说出 K 句话,这 K 句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。

  • 当前的话与前面的某些真的话冲突,就是假话;
  • 当前的话中 X 或 Y 比 N 大,就是假话;
  • 当前的话表示 X 吃 X,就是假话。

你的任务是根据给定的 N 和 K 句话,输出假话的总数。

输入格式

第一行两个整数,N,K,表示有 N 个动物,K 句话。

第二行开始每行一句话(按照题目要求,见样例)

输出格式

一行,一个整数,表示假话的总数。

输入输出样例

输入 #1复制

100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5

输出 #1复制

3

说明/提示

对于全部数据,1≤N≤5×104,1≤K≤105。

解决方案:

和第一个题类似也是一个种类并查集,但是这个题又三个种类,a,b,c,a吃b,b吃c,c吃a

a,b,c分别在1~n,n+1~2n,2n+1~3n;

所以要a和b是同一种类即

merge(x, y);
merge(x + n, y + n);
merge(x + 2 * n, y + 2 * n);

要a吃b即

merge(x, y + n);
merge(x + n, y + 2 * n);
merge(x + 2 * n, y);

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 400000 + 10;
int fa[N];
void init(int x)
{for (int i = 1; i <= x; i++)fa[i] = i;
}
int find(int x)
{if (fa[x] == x)return x;return fa[x] = find(fa[x]);
}
void merge(int x, int y)
{int fx = find(x), fy = find(y);if (fx != fy)fa[fx] = fy;
}//并查集板子
inline void solve()
{int n, m;cin >> n >> m;int op, x, y;init(3*n+100);vector<int> tab(3*n+100, 0);int res = 0;for (int i = 1; i <= m; i++){cin >> op >> x >> y;if (x > n || y > n){res++;continue;}if (op == 1){if (find(x) == find(y + n) || find(x) == find(y + 2 * n))//如果x吃y或者y吃x就说明x,y不可能是同一种类res++;else{merge(x, y);merge(x + n, y + n);merge(x + 2 * n, y + 2 * n);}}else{if (find(x) == find(y)||find(x)==find(y+2*n))//如果x和y是同一种类或者y吃x就不可能存在x吃yres++;else{merge(x, y + n);merge(x + n, y + 2 * n);merge(x + 2 * n, y);}}}cout << res << endl;
}signed main()
{ios::sync_with_stdio(false);cin.tie(0);int t = 1;//cin >> t;while (t--){solve();}
}

http://www.dtcms.com/a/347806.html

相关文章:

  • Day26 树的层序遍历 哈希表 排序算法 内核链表
  • 线程池理解
  • CMake安装教程
  • 传统 AI 与生成式 AI:IT 领导者指南
  • 10.Shell脚本修炼手册---脚本的条件测试与比较
  • 如何查看MySQL 的执行计划?
  • 引领GEO优化服务新潮流 赋能企业数字化转型
  • 信贷模型域——信贷获客模型(获客模型)
  • AI大模型 限时找我领取
  • Transformer核心概念I-token
  • Java:对象的浅拷贝与深拷贝
  • 获取高德地图经纬度解析地址的免费API接口(无调用限制)
  • JWT实现Token登录验证
  • 任务型Agent:执行计划详细设计
  • 计算机组成原理(11) 第二章 - 存储系统的基本概念
  • Introduction to GIS ——Chapter 1(Introduction)
  • 控制建模matlab练习15:线性状态反馈控制器-④最优化控制LQR
  • 动态内存详解
  • 图、最小生成树与最短路径
  • 算法练习-最长连续序列
  • 最短路径和关键路径的算法
  • Linux学习:信号的保存
  • 【什么是大模型自注意力机制?】
  • 腾讯wxg后台开发面经
  • A Large Scale Synthetic Graph Dataset Generation Framework的学习笔记
  • JavaSpring+mybatis+Lombok,实现java架构[保姆教程]
  • KVM虚拟化:提升企业效率的利器
  • 编程刷题-P1746 离开中山路 BFS/最短路径
  • 数据结构算法:顺序表
  • 电脑零广告快响应提速(一)之卸载搜狗输入法使用RIME—东方仙盟