codeforces 873B

题目链接:https://codeforces.com/problemset/problem/873/B

小trick :把 0 看成 -1,求前缀和,
如果区间([l,r])内 0 和 1 数量相等,那么(sum[r] = sum[l-1])
所以只需要记录相同 sum 值出现的最小位置
注意开的记录(bas[i])数组下标可能溢出,要先加上 100000

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;

const int maxn = 100010; 

int n;
int a[maxn],sum[maxn],bas[maxn * 2];
char s[maxn];

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }

int main(){
	memset(bas,-1,sizeof(bas));
	n = read();
	scanf("%s",s+1);
	for(int i=1;i<=n;++i){
		if(s[i] == '0') a[i] = -1;
		else a[i] = 1;
	}
	int ans = 0;
	sum[0] = 100000;
	bas[sum[0]] = 0;
	for(int i=1;i<=n;++i){
		sum[i] = sum[i-1] + a[i];
		if(bas[sum[i]] != -1){
			ans = max(ans, i - bas[sum[i]]);
		}else{
			bas[sum[i]] = i;
		}
	} 
//	for(int i=1;i<=n;++i) printf("%d ",sum[i]); printf("
");
		
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/tuchen/p/13831468.html