SnakeDown 2017 Online Pre-Elimination Round A D 结题报告:三分

xiaoxiao2021-02-28  93

题意:给出一个[1,1e9]的区间,并规定A、B端点,现在有一些长度都是L的线段,散乱分布在整个[1,1e9]的区间内,现在要让所有的线段都移动到[A,B]内,并且首尾相连,求最小的总移动距离之和。保证n*l<=B-A

题解:这个题。。就是个三分。然后当确定最左边线段的码放开始点之后,最小距离之和就是按照原来的左端点的顺序依次码放。要注意最后三分结束之后,枚举答案要用一个for循环从l到r来枚举答案,否则会枚举到非法值。

AC代码:

#include<bits/stdc++.h> using namespace std; #define MAXN 100005 long long aa[MAXN]; long long n,t,a,b,l,ans; long long calc(long long start){ long long ans =0; for (int i=0;i<n;i++){ ans+=abs(aa[i]-start); start+=l; } return ans; } bool cmp(long long a,long long b){ return a<b; } int main(){ cin>>t; while (t--){ cin>>n>>l>>a>>b; for (int i=0;i<n;i++){ scanf("%I64d",&aa[i]); } sort(aa+0,aa+n,cmp); long long ll = a; long long rr = b-l*n; while (rr>ll+2){ int mid = (rr-ll)/3+ll; int mmid = (rr-ll)/3*2+ll; long long midAns = calc(mid); long long mmidAns = calc(mmid); // cout<<"l:"<<ll<<" r:"<<rr<<" mid:"<<mid<<" mmid:"<<mmid<<" midAns:"<<midAns<<" mmidAns"<<mmidAns<<endl; if (midAns<mmidAns){ rr=mmid; }else{ ll=mid; } } ans = calc(ll); for (int i=ll+1;i<=rr;i++){ ans=min(ans,calc(i)); } cout<<ans<<endl; } return 0; }

转载请注明原文地址: https://www.6miu.com/read-84364.html

最新回复(0)