http://pipioj.online/problem.php?id=1413
思路:带权中位数问题,详细证明参见百度百科。先给出结论:
∑
i
=
1
n
∣
x
i
−
x
∣
∗
w
i
\sum_{i=1}^{n}|x_i-x|*w_i
∑i=1n∣xi−x∣∗wi的最小值当且仅当
x
=
x
(
∑
i
=
1
n
w
i
)
/
2
x=x_{(\sum_{i=1}^nw_i)/2}
x=x(∑i=1nwi)/2(此处不细致考虑下标问题)时取得。这里给出我自己的理解(非严谨证明),我们知道
∑
i
=
1
n
∣
x
i
−
x
∣
\sum_{i=1}^{n}|x_i-x|
∑i=1n∣xi−x∣的最小值当且仅当
x
=
x
n
/
2
x=x_{n/2}
x=xn/2(即x等于中位数时)取得,那么对于上面的式子,我们可以把数列从
n
n
n项扩展到
∑
i
=
1
n
w
i
\sum_{i=1}^nw_i
∑i=1nwi项,这样就可以把权值消去,问题转换成了普通的中位数问题,结论依然成立。
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
using ll=long long;
const int maxn=1e5+5;
struct node
{
int x,y,w;
node(int x=0,int y=0,int w=0):x(x),y(y),w(w){}
};
int n;
node a[maxn];
int main()
{
scanf("%d",&n);
int num=0;
for(int i=1;i<=n;i++)
scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].w),num+=a[i].w;
num=(num+1)>>1;
sort(a+1,a+1+n,[](const node &a,const node &b){ return a.x<b.x; });
ll ans=0;
int tmp=0,idx=0,mid;
while(tmp<num)
tmp+=a[++idx].w;
mid=a[idx].x;
for(int i=1;i<=n;i++)
ans+=(ll)abs(a[i].x-mid)*a[i].w;
sort(a+1,a+1+n,[](const node &a,const node &b){ return a.y<b.y; });
tmp=idx=0;
while(tmp<num)
tmp+=a[++idx].w;
mid=a[idx].y;
for(int i=1;i<=n;i++)
ans+=(ll)abs(a[i].y-mid)*a[i].w;
printf("%lld\n",ans);
return 0;
}