Matrix67的非常男女计划 (递推??枚举!!)

【问题描述】

  Matrix67已经当过多次“媒人”了。他因此获得了许多经验。例如,距Matrix67观察,身高相近的人似乎比较合得来。

  Matrix67在学校策划了一次大型的“非常男女”配对活动。对于这次活动的参与者,Matrix67有自己独特的选择方式。他希望能选择男女人数相等且身高都很接近的一些人。这种选择方式实现起来很简单。他让学校的所有人按照身高排成一排,然后从中选出连续的若干个人,使得这些人中男女人数相等。Matrix67当然希望他能选出的人越多越好。请编写程序告诉他,他最多可以选出多少人来。

【输入格式】

  第一行有一个正整数n,代表学校的人数。
  第二行有n个用空格隔开的数,这些数只能是0或1,其中,0代表一个女生,1代表一个男生。

【输出格式】

  输出一个非负整数。这个数表示在输入数据中最长的一段男女人数相等的子序列长度。如果不存在男女人数相等的子序列,请输出0。

【输入样例】
9
0 1 0 0 0 1 1 0 0
【输出样例】

6
【数据范围】

对于30%的数据,n<=100;
对于50%的数据,n<=1 000;
对于100%的数据,n<=100 000。

【来源】
Matrix67原创

【笔者题解】
在输入的时候计算前缀和,如果一个长度为偶数的连续子序列和为长度的一半,说明男女人数一样。
重要的是在枚举中优化:
1.枚举以i为起点,j为终点的连续子序列
2.如果第i个人后面的人数已经小于ans了,就没有必要再枚举下去了
3.i为起点,j的最小值应该是i+ans+1(因为长度小于等于ans的不需要枚举)
4.j每次+2(序列长度为偶数)
优化了之后虽然有两重循环但是跑得极快。

#include<cstdio>
#include<algorithm>
#define maxn 100005
using namespace std;
int n,ans=0;
int a[maxn],sum[maxn]={0};
void read(int &x)
{
    x=0;
    bool ok=0;
    char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    while((ch>='0'&&ch<='9')||ch=='-')
    {
        if(ch=='-') ok=1;
        x=x*10+ch-'0';
        ch=getchar();
    }
    if(ok) x=-x;
}


void in()
{
    read(n);
    for(int i=1;i<=n;i++)
    {
         read(a[i]);
         sum[i]=sum[i-1]+a[i];
    }
}

void task()
{
    for(int i=1;i<=n-ans;i++)
    for(int j=i+ans+1;j<=n;j+=2) if((sum[j]-sum[i-1])*2==j-i+1)
        ans=max(ans,j-i+1);
    printf("%d",ans);
}

int main()
{
    freopen("in.txt","r",stdin);
    in();
    task();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35546348/article/details/52101779