题目描述
近来,初一年的XXX
小朋友致力于研究班上同学的配对问题(别想太多,仅是舞伴),通过各种推理和实验,他掌握了大量的实战经验。例如,据他观察,身高相近的人似乎比较合得来。
万圣节来临之际,XXX
准备在学校策划一次大型的“非常男女”配对活动。对于这次活动的参与者,XXX
有自己独特的选择方式。他希望能选择男女人数相等且身高都很接近的一些人。这种选择方式实现起来很简单。他让学校的所有人按照身高排成一排,然后从中选出连续的若干个人,使得这些人中男女人数相等。为了使活动更热闹,XXX
当然希望他能选出的人越多越好。请编写程序告诉他,他最多可以选出多少人来。
输入格式
第一行有一个正整数n,代表学校的人数。n≤100000
第二行有n个用空格隔开的数,这些数只能是0或1,其中,0代表一个女生,1代表一个男生
输出格式
输出一个非负整数。这个数表示在输入数据中最长的一段男女人数相等的子序列长度。
如果不存在男女人数相等的子序列,请输出0。
输入输出样例
输入 #1
9 0 1 0 0 0 1 1 0 0
输出 #1
6
强大的同机房大佬一眼就看成了KM(读题要仔细啊)
刚开始没思路偷偷看了算法标签之后恍然大悟(还是不熟练啊)
核心思想是前缀和,把女生记为-1,男生记为1,求数组的前缀和,当男生缺一个的时候前缀和的值就表现为-1,女生缺一个的时候就表现为1,利用这个性质,我们再求前缀和的时候把每种情况第一次出现的下标记录一下,在后面遇见相同的情况时两个下标的差值就是一个男女人数相同的区间的长度
以样例为栗:
原数组 0 1 0 0 0 1 1 0 0
前缀和 -1 0 -1 -2 -3 -2 -1 -2 -3
可以很明显的看出在只有一个人的时候缺了一个男生,在第7位的时候还是缺了一个男生那不用想啊,第2位到第7位的男女人数一定相同啊(不然就见鬼了)
ACCODE
#include <iostream>
#include <map>
using namespace std;
map<int,int> mp;//用来存每种情况第一次出现的下标值
int main()
{
int k[100020]={0}; //前缀和数租
int n;
cin>>n;
k[0]=0;
int a;
for(int i=1;i<=n;i++)
{
cin>>a;
if(a==0)
k[i]=k[i-1]-1;
else
k[i]=k[i-1]+1;
if(k[i]!=0&&mp[k[i]]==0)
mp[k[i]]=i;
} //初始化前缀和数租和mp
int ans=0;
for(int i=n;i>0;--i)
{
if(k[i]==0&&i>ans)
ans=i;
else if(k[i]!=0&&mp[k[i]]!=0&&i-mp[k[i]]>ans)
ans=i-mp[k[i]];
} //遍历所有情况找答案
cout<<ans;
return 0;
}