E. Arranging The Sheep

输出将字符串中的全部放到一起所需要的最小步数。

只有当移动的位置是.才能移动

 

中位数:将数组大小为n的数据,从大到小,或者是从小到大排列,那么当n为奇数的时候,中位数就是(n+1)/2的这个数,当n为偶数的时候,中位数就是n/2和(n+1)/2这二个数据的平均数。

所有元素到中位数的距离之和最小

 

设有X1, X2,..., Xn N个数, 要找出它们在数轴上距离之和最近的一个点x

那么x一定在X1 和 Xn之间,由于X1 和 Xn之间上的任意一点到X1 和Xn的距离固定,所以我们不考虑X1 和 Xn

那么x一定在X2 和Xn-1之间,

依此类推......可以知道x这N个数的中位数

void solve(){
    int sum=0;
    cin>>n>>s+1;
    for(int i=1;i<=n;++i) {
        if(s[i]=='*')    sum++;
    }
    sum=(sum+1)/2;
    int cnt=0,pos=0;
    for(int i=1;i<=n;++i){
        if(s[i]=='*'){
            cnt++; 
        }
        if(cnt==sum){
            pos=i;break;
        }
    }
    cnt=0;int ans=0;
    for(int i=1;i<=n;++i){
        if(s[i]=='*'){
            cnt++;
            ans=ans+abs(pos-i)-abs(sum-cnt); 
        }
    }
    cout<<ans<<"\n";
}

 

dp

移动到i左侧和右侧各自的花费

ll l[maxn],r[maxn],cntl[maxn],cntr[maxn];
ll cal(ll x,ll y)
{
    if(x>y)return 0;
    return ((x+y)*(y-x+1)/2);
}
void solve()
{
    cin>>n;
    cin>>s;
    l[0]=r[n+1]=0;
    cntl[0]=cntr[n+1]=0;
    rep(i,1,n)l[i]=l[i-1]+(s[i-1]=='*')*i,cntl[i]=cntl[i-1]+(s[i-1]=='*');
    dec(i,n,1)r[i]=r[i+1]+(s[i-1]=='*')*i,cntr[i]=cntr[i+1]+(s[i-1]=='*');
    ll ans=INF;
    rep(i,1,n)
        ans=min(ans,cal(i-cntl[i]+1,i)-l[i]+r[i+1]-cal(i+1,i+cntr[i+1]));
    cout<<ans<<"\n";
}

 

posted @ 2021-05-06 23:19  PdrEam  阅读(77)  评论(0编辑  收藏  举报