分析

本题题意为求一串01数字中,每个0距离最近的1的距离之和。

做法1

统计出连续0个数的数组,若有n个连续0:1、首尾的连续0,则distance_sum=(n+1)n/2;2、中间的连续0,则distance_sum=2((n/2+1)*n/2/2),如果n为奇数还要再加上n/2+1。

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
    int t,n;
    scanf("%lld",&t);
    for(int p=1;p<=t;p++)
    {
		vector<int> k;
		int b,startwith0=0,endwith0=0,cnt0=0;
		char c;
        printf("Case #%lld: ",p);
        scanf("%lld",&n);
		getchar();
		for(int i=0;i<n;i++)
		{
			c=getchar();
			b=c-'0';
			if(!i&&!b)startwith0=1;
			if(i==n-1&&!b)endwith0=1;
			if(!b)cnt0++;
			else
			{
				k.push_back(cnt0);
				cnt0=0;
			}
		}
		k.push_back(cnt0);
		int l=k.size(),start=0,end=l-1;
		long long ans=0;
		if(startwith0)
		{
			ans+=(k[0]+1)*k[0]/2;
			start=1;
		}
		if(endwith0)
		{
			ans+=(k[l-1]+1)*k[l-1]/2;
			end=l-2;
		}
		for(int i=start;i<=end;i++)
		{
			if(k[i]%2)
			{
				ans+=2*((k[i]/2+1)*(k[i]/2)/2)+k[i]/2+1;
			}
			else
			{
				ans+=2*((k[i]/2+1)*(k[i]/2)/2);
			}
		}
		printf("%lld\n",ans);
    }
    return 0;
}

做法2

从前往后扫一遍,得到每个0距离左边1的最近距离;再从后往前扫一遍,得到每个0距离右边1的最近距离;然后两个数组比较取其大相加即可。