P1114 “非常男女”计划

我理解的题目意思

给出一个数组由n个 0 或 1 组成,找出包含相同数目的0和1的最长子数组的长度。

$$1≤n≤10^5$$

解题思路

一开始想的很简单,维护一个前缀和数组a记录到当前位置一共多少1,再用一个嵌套for循环遍历子数组,$a[j]-a[i-1]=(j-i+1)/2,j-i+1%2=0$ 满足的条件下输出最大的 j-i+1。注意到 $1≤n≤10^5$ ,O(n²)的复杂度下会超时,需要改换复杂度更低的方法。

O(n)解法:将女视为-1,将男视为1,问题转换为最长的和为0的子数组。用哈希表fs记录前缀和sum,先插入一个 fs[0]=0,再遍历查找是否有 fs[i]=sum ,若有则输出最大的 i-fs[sum] ,否则插入 fs[sum]=i 。

代码:

#include <iostream>
#include <unordered_map>
using namespace std;

int n;
int main()
{
    cin >> n;
    unordered_map<int,int>fp;
    fp[0]=0;
    int ans=0,sum=0;
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        sum+=(x==1)?1:-1;
        if(fp.find(sum)!=fp.end()){
            ans=max(ans,i-fp[sum]);
        }
        else{
            fp[sum]=i;
        }
    }
    cout<<ans;

    return 0;

}