题面:
真是引人浮想联翩的题目呢~在千万题海中一眼选中!
解题:
引入数组d[ i ]储存第i个位置及它本身之前,男生数-女生数的和;
这样,d[ i ]相等的两个数围成的区间,男生数=女生数,即我们所求的合法区间,
定义两个数组,l[ ]和r[ ],储存每个d[ i ]可能值的最左、最右出现的位置,
枚举所有d[ i ]可能值,过程中不断更新ans的最大值
注意:首端也需要默认为一个0的位置,即:d[0]=0,
否则对于2 1 0这样需要连接至首端的数据,给出的答案为0!
AC代码奉上
#include<iostream>
#include<algorithm>
#define MAXN int(1e6+5)
using namespace std;
int n, p, ans = 0, minNum = MAXN, maxNum = -1, d[MAXN] = { 0 }, l[MAXN] = { 0 }, r[MAXN] = { 0 };
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> p;
if (p == 1)d[i] = d[i - 1] + 1;
else d[i] = d[i - 1] - 1;
minNum = min(minNum, d[i]);
maxNum = max(maxNum, d[i]);
}
for (int i = 1; i <= n; i++)
{
if (l[d[i]] == 0 && d[i] != 0) { l[d[i]] = i; } //没有左极限,初始化左极限
else { r[d[i]] = i; } //若发现更大的右极限,不断右移右区间
}
if (r[0] != 0)ans = max(ans, r[0]); //首个数字前有个隐藏的d[0]=0
for (int i = minNum; i <= maxNum; i++)
if (l[i] != 0 && r[i] != 0)
ans = max(ans, r[i] - l[i]);
cout << ans << endl;
return 0;
}