题目链接:https://arc100.contest.atcoder.jp/tasks/arc100_a
题意:
求对于所有的b,
的最小值
题解:
贪心:
显然问题可以转化成p[i]=a[i]-i, 求abs(p[i]-b)之和
枚举b在第k个位置大于p,则答案即为
p
[
k
+
1..
n
]
−
p
[
1..
k
]
+
(
2
∗
k
−
n
)
∗
a
[
k
/
k
+
1
]
p[k+1..n]-p[1..k]+(2*k-n)*a[k / k+1]
p[k+1..n]−p[1..k]+(2∗k−n)∗a[k/k+1]再分析一下2*k-n的正负即可
代码:
// by Balloons
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() puts("okkkkkkkk")
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
using namespace std;
typedef long long LL;
#define int LL
const int inf = 1e9, maxn=2e5+5;
int n,a[maxn],sum[maxn];
signed main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]), a[i] -= i;
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)sum[i] = sum[i-1]+a[i];
LL ans=1e18;
for(int k=1;k<=n;k++){
int oth = sum[k] - (sum[n]-sum[k]);oth *= -1;
int id = 2*k-n;
if(id > 0 || k == n)ans = min(ans,oth+id*a[k]);
else ans = min(ans,oth+id*a[k+1]);
// printf("%lld\n",oth);
}
printf("%lld\n",ans);
return 0;
}
三分:
显然原式对b是一个单峰函数,用三分即可解决
// by Balloons
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() puts("okkkkkkkk")
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
using namespace std;
typedef long long LL;
#define int LL
const int inf = 1e9,maxn=2e5+5;
int n,a[maxn];
int solve(int x){
int r=0;
for(int i=1;i<=n;i++)r += abs(a[i]-x);
return r;
}
signed main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]), a[i] -= i;
int l=-1e9, r=1e9;
while(l<r-1){
int lmid = (l+r)>>1, rmid = (lmid+r) >> 1;
if(solve(lmid) > solve(rmid))l=lmid;
else r=rmid;
}
// printf("%d %d\n",l,r);
int ans;
if(solve(l)<solve(r))ans=l;
else ans=r;
// printf("? %d\n",ans);
printf("%lld\n",solve(ans));
return 0;
}