【基础完全搜索】USACO Bronze 2022 Open - 谎言的人数Counting Liars
题目描述
奶牛 Bessie 藏在数轴上的某个位置。农夫约翰的另外 NNN 头奶牛(1≤N≤10001 \le N \le 10001≤N≤1000)每一头都提供了一条信息:第 iii 头奶牛表示,Bessie 的位置要么小于等于 pip_ipi,要么大于等于 pip_ipi。
但不幸的是,并不是所有奶牛都一定说了实话 —— 有可能没有任何一个位置能够同时满足所有奶牛的描述。
你的任务是:统计最少有多少头奶牛在说谎。
输入格式
第一行输入一个整数 NNN。
接下来的 NNN 行,每行包含一个字符和一个整数,用空格分隔:字符是 LLL 或 GGG。
-
LLL 表示“Bessie 的位置小于等于 pip_ipi”
-
GGG 表示“Bessie 的位置大于等于 pip_ipi”
整数 pip_ipi 表示这头奶牛提供的位置信息,0≤pi≤1090 \le p_i \le 10^90≤pi≤109
输出格式
输出一个整数,表示最少有多少头奶牛在说谎。
样例输入 1
2
G 3
L 5
样例输出 1
0
样例输入 2
2
G 3
L 2
样例输出 2
1
说明/提示
样例解释 111:
Bessie 可能在 [3,5][3, 5][3,5] 之间的任何位置,两头奶牛都可能说了实话。
样例解释 222:
没有任何位置同时满足 x≥3x \ge 3x≥3 且 x≤2x \le 2x≤2,因此至少有一头奶牛在说谎。
数据范围
-
1≤N≤10001 \le N \le 10001≤N≤1000
-
0≤pi≤1090 \le p_i \le 10^90≤pi≤109
提交链接
Counting Liars
思路分析
🧠 思路核心回顾
如果我们假设 Bessie 躲在位置 xxx,那么有两种撒谎的情况:
说 L pi
,但 pi < x
:意思是这个人说 Bessie ≤ pi
,但 Bessie 比它大 → 撒谎
说 G pi
,但 pi > x
:这个人说 Bessie ≥ pi
,但 Bessie 比它小 → 撒谎
于是我们可以:
把所有奶牛按 pi
排序,枚举所有的 pi
值(作为 Bessie 可能的位置),每次都数一下满足以上两类的奶牛有几个,加起来就是撒谎人数。
-
输入处理
将每头奶牛的说法存储为 (位置pi
, 类型G/L
)。 -
排序
将所有奶牛按位置从小到大排序。 -
撒谎规律分析
-
如果一个奶牛说
L x
,她认为 Bessie ≤ x;- 若 Bessie 实际位置 > x(即比她右边),她在撒谎;
- 所以我们需要统计:在当前位置左边,说
L
的奶牛数量。
-
如果一个奶牛说
G x
,她认为 Bessie ≥ x;- 若 Bessie 实际位置 < x(即比她左边),她在撒谎;
- 所以我们需要统计:在当前位置右边,说
G
的奶牛数量。
-
-
建立两个数组
lying_left[i]
:Bessie 躲在第i
个奶牛的位置时,左边有多少说L
的奶牛在撒谎。lying_right[i]
:Bessie 躲在第i
个奶牛的位置时,右边有多少说G
的奶牛在撒谎。
-
遍历所有位置
-
计算
lying_left[i] + lying_right[i]
,即 Bessie 躲在当前位置时的总撒谎数。 -
最终答案为所有位置中撒谎数的最小值。
-
参考代码
#include <bits/stdc++.h>
using namespace std;int main()
{int n;cin >> n;vector<pair<int, char>> p(n);for (auto &[x, y] : p)cin >> y >> x; // G x(>=pi) L x(<=pi) 两种情况sort(p.begin(), p.end());vector<int> lying_left(n) , lying_right(n);for (int i = 1; i < n; i++){lying_left[i] += lying_left[i - 1];if (p[i - 1].second == 'L')lying_left[i]++;}for(int i = n - 2; i >= 0; i--){lying_right[i] += lying_right[i + 1];if(p[i + 1].second == 'G')lying_right[i]++;}int mi = n;for(int i = 0; i < n; i++)mi = min(mi , lying_left[i] + lying_right[i]);cout << mi;return 0;
}