【noi.ac #562】T3

题目

给定一个01环,每次可以交换相邻的两个数字,问最少多少次能使0和1分别在连续的一段区间。

有 T 组数据。

n<=1e6 T<=10

思路

先把环倍长,然后可以发现我们的过程是将0or1往中间靠拢,而且一定满足是往中位数靠,所以我们枚举长度为n的段,然后计算往中间靠拢的代价就行。

考场上没想到倍长,结果大样例没过,还不如暴力

代码

#include
#define ll long long
using namespace std;
const int N=1e6+77;
char st[N];
int cnt=0;
ll s[N],_1[N];
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%s",st);
		ll n=strlen(st);
		cnt=0;
		for(int i=0; i<(n<<1); i++) if(st[i%n]-'0') _1[++cnt]=i;
		ll p=cnt>>1,mid=(p+1)>>1;
		for(int i=1; i<=cnt; i++) s[i]=s[i-1]+_1[i];
		ll ans=0x3f3f3f3f3f3f3f3f;
		for(ll i=1; i<=p+1; i++) ans=min(ans,_1[i+mid-1]*mid-s[i+mid-1]+s[i-1]+s[i+p-1]-s[i+mid-2]-_1[i+mid-1]*(p-mid+1));
		printf("%lld\n",ans-mid*(mid-1)/2-(p-mid)*(p-mid+1)/2);
	}
}

你可能感兴趣的:(【noi.ac #562】T3)