个人训练11 问题 G: 野牛与狼

                                     努力做好每一件事吧

                                 想都是问题,做才是答案!

题目描述

位于欧洲中部的赫希费尔登狩猎保护区生活着许多动物,雄壮的野牛和凶狠的狼群之间保持着一种平衡,当野牛的数量和狼群一样多时,它们彼此互不侵犯相安无事,但只要狼的数量多于野牛狼群就会攻击牛群,而野牛数量占多数时,它们会驱逐狼群到别的地方。
当地的统计学家把牛群和狼群分布通过0和1表示为一个字符串S,S的字串可以表示一个区域内的牛和狼总数,请你根据这个统计字符串,判断出来这个保护区内能共存最多头野牛和狼的区域,该区域的牛群和狼群总数是多少。

输入

一个字符串,只包含01,长度不超过1000000。

输出

一行一个整数,最长的0与1的个数相等的子串的长度。

样例输入 

1011

样例输出

2

对于1011而言,它表示保护区内分布情况为:[牛,狼,牛,牛],那么最多只有[狼,牛]这2只动物存在于某个区域内,所以结果为2
对于10%的数据,字符串长度≤10; 
对于100%的数据,字符串长度≤1000000。

看了题解才知道这道题目的巧妙,主要就是利用了前缀和思想,但是一些需要注意的地方。记录整个数组的前缀和,遇到 ‘0’ 当做-1。

我想记录当前点的前缀和出现的最早位置,但是当前点的前缀和可能是负数,那么用数组下标记录就会出现问题了,那么就像整个数组下标+上一个保险的数就好了,总之这题还是很巧妙的。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<map>
using namespace std;
const int maxn=2000000+10;
int sum[maxn],tag[maxn],ans;
char s[maxn];
int main()
{
	scanf("%s",s);
	int len=strlen(s);
	for(int i=len;i>=1;i--)
	{
		s[i]=s[i-1];
	}
	for(int i=1;i<=len;i++)
	{
		if(s[i]=='1')
		sum[i]=sum[i-1]+1;
		else if(s[i]=='0')
		sum[i]=sum[i-1]-1;
	}
	for(int i=1;i<=len;i++)
	{
		if(sum[i]==0)
		{
			ans=max(ans,i);
		}
		if(tag[sum[i]+maxn/2]==0)
		{
			tag[sum[i]+maxn/2]=i;
		}
		if(tag[sum[i]+maxn/2])
		{
			ans=max(ans,i-tag[sum[i]+maxn/2]);
		}
	}
	printf("%d",ans);
	return 0;
}
发布了51 篇原创文章 · 获赞 21 · 访问量 3086

猜你喜欢

转载自blog.csdn.net/qq_44115065/article/details/102826841