1、题目表述
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题号:NC207053
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
我们刚刚学了二分查找——所谓二分查找就是在一堆有序数里找某个符合要求的数。在学完二分查找之后如果让你玩猜数游戏(裁判选定一个目标数字,你说一个数裁判告诉你是高了还是低了直到你猜到那个数)的话,显然你会用二分的方式去猜。
但是不是每一个玩猜数游戏的人都知道二分是最好,甚至一个健忘的玩家都有可能在得到裁判回答的下一个瞬间就忘了他之前问了什么以及裁判的回答),而现在更可怕的是,这个告诉你猜的数是高还是低的裁判他也很健忘,他总是薛定谔的记得这个目标数字,也就是说他的回答有可能出错。我们已经不关心这个不靠谱的游戏本身了,我们更关心裁判这个薛定谔的记得到底有几个是记得......
现在给出这个健忘的玩家的所有猜测和裁判的所有回答,问裁判最多能有多少次是记得目标数字的,即裁判的回复是符合情况的。
输入描述:
第一行包含一个正整数n,表示裁判的回答数(也是玩家的猜数次数)。
接下来n行,首先是猜的数,然后是一个空格,然后是一个符号。符号如果是“+”说明猜的数比答案大,“-”说明比答案小,“.”说明猜到了答案。
输出描述:
包含一个正整数,为裁判最多有多少个回答是正确的。
示例1
输入
4
5 .
8 +
5 .
8 -
输出
3
说明
当目标数组是5时,5 . 5 . 8 + 这三个回答都是正确的
备注:
n≤100000
所有数的大小都小于int类型最大值。
2、思路
该题让我们根据裁判的回答和与正确数值的关系(实际上就是给出可能正确的数值的范围)来计算出裁判最多有多少回答是正确的。若为 "x . ",正确区间就是 [x]; 若为"x -",正确区间就是
[x+1,∞);若为"x +",正确区间就是(-∞,x-1]。
由于题干有提示“所有数的大小都小于int类型最大值”,int最大数值小于 1e11,所以本题中1e11可以等效为 ∞。
假设区域在[n, m],那么就让[n]++,[m+1]--。用 n 位置的数值大小来代表所有的n~m这个区域上的正确的次数,这样在(-∞,n)的前缀和就是 0 ,在[n,m]的前缀和就是 1 ,在(m,∞)前缀和复归 0。(差分前缀和)
在此题上就是
x . [x]++ [x+1]--
x + [-∞]++ [x]--
x - [x+1]++ [∞]--
然后由于int数值范围太大,所以用map来存取位置,用foreach来遍历map,在map中会自动把int、long long类型的数值按键值升序排列,正好符合前缀和计算需求。
3、代码
#include<bits/stdc++.h>
using namespace std;
map<long long, int> a;
int main()
{
int i, j;
int n;
long long maxer = 1e11;
cin >> n;
for (i = 1; i <= n; i++)
{
int x;
char c;
cin >> x >> c;
if (c == '.')
{
a[x]++;
a[x + 1]--;
}
else if (c == '+')
{
a[-maxer]++;
a[x]--;
}
else
{
a[x + 1]++;
a[maxer]--;
}
}
int sum = 0;
int result = 0;
for (auto it : a)
{
sum += it.second;
result = max(result, sum);
}
cout << result;
return 0;
}