链接:https://ac.nowcoder.com/acm/problem/207053
来源:牛客网
我们刚刚学了二分查找——所谓二分查找就是在一堆有序数里找某个符合要求的数。在学完二分查找之后如果让你玩猜数游戏(裁判选定一个目标数字,你说一个数裁判告诉你是高了还是低了直到你猜到那个数)的话,显然你会用二分的方式去猜。
但是不是每一个玩猜数游戏的人都知道二分是最好,甚至一个健忘的玩家都有可能在得到裁判回答的下一个瞬间就忘了他之前问了什么以及裁判的回答),而现在更可怕的是,这个告诉你猜的数是高还是低的裁判他也很健忘,他总是薛定谔的记得这个目标数字,也就是说他的回答有可能出错。我们已经不关心这个不靠谱的游戏本身了,我们更关心裁判这个薛定谔的记得到底有几个是记得......
现在给出这个健忘的玩家的所有猜测和裁判的所有回答,问裁判最多能有多少次是记得目标数字的,即裁判的回复是符合情况的。
n100000
所有数的大小都小于int类型最大值。
本题中的数值过大,无法开辟出数组去解答。使用map去离散化求解。
使用差分和求前缀和的方式。
以题目上为例:如果ch=='.'的话就让当前的数对应的值加一。
如果ch=='+'的话就让前面的数都加一。
如果ch=='-'的话就让后面的数都加一。
当然虽然说是加一,但遍历加一操作时间和空间上肯定都是不够的,所以要使用差分和前缀和的方式去计算。
代码:
//使用差分的方式去计算,由于数据过大开辟不出来这么大的数组,所以使用map去保存。
#include <iostream>
#include <cstdio>
#include <limits.h>
#include <map>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

using namespace std;

const int inf = INT_MAX;
int main() {
    map<int, int > m = {};
    int n;
    int k;
    char a;
    cin>>n;
    for (int i=0;i<n;i++) {
        cin>>k>>a;
        if (a=='.') {
            m[k]+=1;
            m[k+1]-=1;
        }
        if (a=='+') {
            m[-inf]+=1;
            m[k]-=1;
        }
        if (a=='-') {
            m[inf]--;
            m[k+1]+=1;
        }
    }
    map<int, int>::iterator it = m.begin();
    int maxn = -inf;
    int h = 0;
    for (it; it!=m.end();it++) {
//         cout<<it->second<<endl;
        h+=it->second;
//         cout<<h<<" "<<it->second<<endl;
        if (h>maxn) {
            maxn = h;
        }
    }
    cout<<maxn;
    return 0;
}