如果有一段区间
特殊点:需要特判
k1==k2 男女数相同,他们的l[t]一定是0,r[t]可以变化
所以只有k1=k2 t!=n l数组才可以存下标,不然会出错
所以需要增加一个特判 t!=n
特殊情况:需要特别处理
由于男生数k1,女生数k2,t=k1-k2可能会小于0,会导致下标越界
那么我们让t+=n,变成t=k1-k2+n 下标就不会越界了
注意 要么不加,然后所有涉及到t的地方都写成t+n
要么直接加上 比较方便
相对差
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
const int N = 1E6 + 5;
int l[2*N], r[2*N]; //l表示第一个出现某个下标的位置,r表示最后一个出现某个下标的位置
int a[N];
int main()
{
int n;
cin >> n;
int k1 = 0,k2=0; //0~某点 相对差
for (int i = 1;i <= n;i++)
{
cin >> a[i];
if (a[i]) k1 += 1;
else k2 += 1;
//这里可能k会小于0,+n优化
int t = k2 - k1 + n;
if (!l[t]&&t!=n) l[t] = i;
//t!=n 一定要加 如果k2==k1 说明0~这一点男女数相同
else r[t] = i;
}
int res = 0;
for (int i = 1;i <=2*n;i++)
{
res = max(res, r[i] - l[i]);
}
cout << res;
}
前缀和剪枝
这题用前缀和来做的话会发现一个性质
1.一个区间的和如果==区间长度/2 那么这个区间必然是男女生能够全部匹配的
但是这样子做的时间复杂度是O(N^2) ,我们通过暴力剪枝,如果枚举的区间长度<res,就不枚举了
可以有效地降低时间复杂度
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100005;
int a[N];
int s[N];
int main()
{//前缀和 O(n^2)会超时
//和dfs剪枝类似,采用
int n;
cin >> n;
for (int i = 1;i <= n;i++)
{
cin >> a[i];
s[i] = s[i - 1] + a[i];
}
int ans = 0;
for (int i = 1;i <= n;i++)
{
for(int j = n;j >= i;j--)
{
if (j - i + 1 < ans)
break;
if ((s[j] - s[i - 1]) * 2 == j - i + 1)
ans = max(j-i+1, ans);
}
}
cout << ans;
}