Codeforces Round #719 (Div. 3) E. Arranging The Sheep(字符串+中位数定理)

https://codeforces.com/contest/1520

你在玩“放羊”游戏。这个游戏的目标是让羊排好队。

游戏中的关卡由一个长度为n的字符串描述,由字符“.”组成(空格)和' * '(羊)。

在一次移动中,你可以将任何羊向左移动一格或向右移动一格,如果相应的方格存在并且是空的。

羊一排好,游戏就结束了,也就是说,任何羊之间都不能有空格。

输出
对于每个测试用例输出,您需要完成该级别的最少移动次数。
input 
5
6
**.*..
5
*****
3
.*.
3
...
10
*.*...*.**
output 
1
0
0
0
9

方法一:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=200200,M=2002;
LL a[N],b[N];
int main()
{
    cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
    int T=1;
    cin>>T;
    while(T--)
    {
        LL n;
        cin>>n;
        string s;
        cin>>s;
        LL l=0,r=0;
        for(int i=0;i<n;i++)
            if(s[i]=='*') r++;
        LL sum=0;
        for(int i=0;i<n;i++)
        {
            if(s[i]=='*') l++,r--;
            else sum+=min(l,r);
        }
        cout<<sum<<endl;
    }
    return 0;
}

方法二:

  • 先找到每个*的所在位置
  • 然后按顺序排序的话,每个*接在前一个的后面需要向前移动多少位置(也就是代码中的偏移量)
  • 然后知道了这所有星星黏在一起需要的步数后,用中位数求得最小合并距离

———知识分割线———
中位数定理
给定数轴上的n个点,找出一个到它们的距离之和尽量小的点
结论:这些点的中位数就是目标点。
根据中位数定理,我们可以想到,找到中间的那个星号,然后让其他点都凑到这个点,最终就是答案了。
这样就只用选一个点就够了,刚好是o(n)的。

        LL n;
        cin>>n;
        string s;
        cin>>s;
        s=" "+s;
        LL k=0;
        for(int i=1;i<=n;i++)
            if(s[i]=='*') b[++k]=i;
        for(int i=1;i<=k;i++)
        {
            b[i]-=i;//减去偏移量
            //cout<<b[i]<<" ";
        }
        LL sum=0;
        for(int i=1;i<=k;i++)
            sum+=abs(b[i]-b[k/2+1]);
        cout<<sum<<endl;
posted @ 2022-09-03 10:55  Vijurria  阅读(36)  评论(0编辑  收藏  举报