题解:AT_abc393_d [ABC393D] Swap to Gather

AT_abc393_d [ABC393D] Swap to Gather 题解

题意

给定一串只有 01的字符串,可以将相邻的两个字符交换,问至少需要多少步才能让所有的 1相邻。

思路

非常结论的一道题目。

设有 mmm1,则把所有的 1都移到与第 m2+1\frac{m}{2}+12m+11相邻的位置有最优解。

为什么,举例说明一下:

mmm 为奇数。

假设有这么一串数:

10⋯0⏟a个010⋯0⏟b个011\underbrace{0\cdots 0}_{a个0}1\underbrace{0\cdots 0}_{b个0}11a0001b0001

若把所有的 1都移到与中间那个 1相邻的位置,则所需步数为:a+ba+ba+b

若要把所有的 1都移到与两旁的 1相邻的位置,则所需步数为:a+2×ba+2\times ba+2×b2×a+b2\times a+b2×a+b

很显然,这两个答案一定都会比 a+ba+ba+b 大。所以,在 mmm 为奇数时,把所有的 1都移到与第 m2+1\frac{m}{2}+12m+11相邻的位置时有最优解。

mmm 为偶数。

假设有这么一串数:

10⋯0⏟a个010⋯0⏟b个010⋯0⏟c个011\underbrace{0\cdots 0}_{a个0}1\underbrace{0\cdots 0}_{b个0}1\underbrace{0\cdots 0}_{c个0}11a0001b0001c0001

若要移到与第一个 1相邻的位置,则所需步数为:a×3+b×2+ca\times 3+b\times 2+ca×3+b×2+c

若要移到与第二个 1相邻的位置,则所需步数为:a+b×2+ca+b\times 2+ca+b×2+c。同理,移到与第三个 1相邻的位置所需步数也是:a+b×2+ca+b\times 2+ca+b×2+c

若要移到与第四个 1相邻的位置,则所需步数为:a+b×2+c×3a+b\times 2+c\times 3a+b×2+c×3

此时,可以发现把所有的 1都移到与第 m2\frac{m}{2}2m1到第 m2+1\frac{m}{2}+12m+11相邻的位置时都有最优解。所以不妨也把所有的 1都移到与第 m2+1\frac{m}{2}+12m+11相邻的位置。

其实这题就是一个绝对值方程求最值。

代码

直接模拟即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 5e5 + 10;
int n;
char a[MAXN];
int num;

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for(register int i = 1;i <= n;i ++) {
		cin >> a[i];
		if(a[i] == '1')
			num ++;	
	}
	int k , cnt = 0 , ans = 0;
	for(register int j = 0 , i = 1;j < num / 2 + 1;i ++)
		if(a[i] == '1') {
			k = i;
			j ++;
		}
	for(register int i = k - 1;i >= 1;i --)
		if(a[i] == '1') {
			ans += (k - i - 1 - cnt);
			cnt ++;
		}
	cnt = 0;
	for(register int i = k + 1;i <= n;i ++)
		if(a[i] == '1') {
			ans += (i - k - 1 - cnt);
			cnt ++;
		}
	cout << ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值