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;
}