专栏文章
AT_abc393_d [ABC393D] Swap to Gather 题解
AT_abc393_d题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miq2xqyl
- 此快照首次捕获于
- 2025/12/03 22:05 3 个月前
- 此快照最后确认于
- 2025/12/03 22:05 3 个月前
AT_abc393_d [ABC393D] Swap to Gather 题解
题面翻译
题目描述
给定一个长度为 的
01串。保证 中至少包含一个1。你可以进行以下操作任意(可以为零)次:
- 选择一个整数 ,并交换 的第 和第 个字符。
找到使所有
1连续的最少操作次数。本题中,所有
1连续当且仅当:输入格式
共两行,第一行一个整数 ,第二行一个字符串 ,意义如上。
输出格式
一行一个整数,表示答案。
数据保证
- 为整数
- 为
01串 - 中至少有一个
1
思路
前置知识
取最小值当且仅当:
x\in [a_\frac{n}{2},a_\frac{n+2}{2}] &\text{if } 2|a \\
x=a_\frac{n+1}{2} &\text{otherwise}
\end{cases}$$
### 思路
注意到,在最优方案中,所有`1`的相对位置都不变。因此,对于一个连续处左端点 $l$,第 $i(1\le i\le k)$($k$ 为`1`的个数)个`1`会到位置 $l+i-1$。于是可得连续出左端点 $l$ 所对应的代价为:
$$cost_l=\sum^k_{i=1}|p_i-(l+i-1)|=\sum^k_{i=1}|l-(p_i+i-1)|$$
其中,$p_i$ 为第 $i$ 个`1`的初始位置。
我们可以 $O(n)$ 预处理出 $(p_i-i+1)$。根据**前置知识**可知,当 $l=\lfloor \frac{k}{2}\rfloor$ 时,$cost$ 取最小值。
另外,注意到 $\forall 2\le i\le k,p_i-p_{i-1}\ge 1$,因此 $(p_i-i+1)-[p_{i-1}-(i-1)+1]=p_i-p_{i-1}+1>0$,即 $(p_i-i+1)$ 单调递增,无需排序即可 $O(1)$ 求出中位数。
### 解法
令 $pos_i=p_i-i+1$。
1. 预处理出 $p_i$、$pos_i$。
2. 将 $pos$ 的中位数代入 $cost$,求出答案。
### 时间复杂度
显然为 $O(n)$。
## AC Code
```cpp
#include <bits/stdc++.h>
#define int long long
using namespace std;
string s;
int n, tot;
vector<int> pos;
int cal(int pos){
int res = 0, cnt = 0;
for(int i = 1; i <= n; ++ i) if(s[i] == '1') res += abs(pos + (cnt ++) - i);
return res;
}
signed main(){
cin >> n >> s;
s = " " + s;
for(int i = 1; i <= n; ++ i) if(s[i] == '1') pos.push_back(i - (tot ++));
cout << cal(pos[pos.size() >> 1]) << endl;
}
```相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...