题目描述
我们刚刚学了二分查找——所谓二分查找就是在一堆有序数里找某个符合要求的数。在学完二分查找之后如果让你玩猜数游戏(裁判选定一个目标数字,你说一个数裁判告诉你是高了还是低了直到你猜到那个数)的话,显然你会用二分的方式去猜。
但是不是每一个玩猜数游戏的人都知道二分是最好,甚至一个健忘的玩家都有可能在得到裁判回答的下一个瞬间就忘了他之前问了什么以及裁判的回答),而现在更可怕的是,这个告诉你猜的数是高还是低的裁判他也很健忘,他总是薛定谔的记得这个目标数字,也就是说他的回答有可能出错。我们已经不关心这个不靠谱的游戏本身了,我们更关心裁判这个薛定谔的记得到底有几个是记得......
现在给出这个健忘的玩家的所有猜测和裁判的所有回答,问裁判最多能有多少次是记得目标数字的,即裁判的回复是符合情况的。
输入描述:
第一行包含一个正整数n,表示裁判的回答数(也是玩家的猜数次数)。接下来n行,首先是猜的数,然后是一个空格,然后是一个符号。符号如果是“+”说明猜的数比答案大,“-”说明比答案小,“.”说明猜到了答案。
输出描述:
包含一个正整数,为裁判最多有多少个回答是正确的。
输入
4 5 . 8 + 5 . 8 -
输出
3
说明
当目标数组是5时,5 . 5 . 8 + 这三个回答都是正确的
备注:
n≤100000 所有数的大小都小于int类型最大值。
———————————————————————————————————————————
题解:
我们可以根据裁判给出的回答得出如果他回答正确的话那么正确的数据应该有哪些。记猜的数为a,如果符号是'.'说明正确的数据是a;如果符号是'-'说明正确的数据是[a+1,正无穷大],如果符号是'+'说明正确的数据是[负无穷大,a-1]。把每次说法对应正确的数据大小加1,在最后遍历所有数据,那么最大的一个就表示取它为目标数字就能得到最多的正确次数。
由于符号'-'和'+'是需要对一个区间上的数据进行+1操作,所以很明显用差分去完成。
差分的前缀和得到的就是原数组,这里要注意差分数组不可以用int数组存储,因为我们这里用到了负无穷到正无穷,数据量过大,数组存不下。
#include<iostream>
#include<limits.h>
#include<map>
using namespace std;
map<int,int>d;
int main(){
ios::sync_with_stdio(false);
cout.tie(0);cin.tie(0);
int n,i,a,ans=0,x=0;
char c;
cin>>n;
for(i=0;i<n;i++){
cin>>a>>c;
if(c=='.'){
d[a]++;
d[a+1]--;
}
else if(c=='+'){
d[-INT_MAX]++;
d[a]--;
}
else{
d[a+1]++;
d[INT_MAX]--;
}
}
for(auto m:d){
//差分数组的前缀和,即m对应的数据的正确次数
x+=m.second;
ans=max(ans,x);
}
cout<<ans;
return 0;
}