http://pipioj.online/problem.php?id=1413
アイデア:加重中央値問題。詳細な証拠については、Baidu百科事典を参照してください。最初に結論を出します。∑ i = 1 n ∣ xi − x ∣ ∗ wi \ sum_ {i = 1} ^ {n} | x_i-x | * w_i∑i = 1n個∣ x私−x ∣∗w私x = x(∑ i = 1 nwi)/ 2 x = x _ {(\ sum_ {i = 1} ^ nw_i)/ 2}の場合の最小値バツ=バツ(∑i = 1n個w私)/ 2(ここでは添え字の問題を慎重に検討していません)。これが私自身の理解です(厳密ではない証明)。∑ i = 1 n ∣ xi − x ∣ \ sum_ {i = 1} ^ {n} | x_i-x |∑i = 1n個∣ x私−最小値X |場合にのみ、X = XN / 2×= X_ {N / 2}バツ=バツN / 2(つまり、xが中央値に等しい場合)、上記の式では、nnから数列をとることができます。n個のアイテムが∑ i = 1 nwi \ sum_ {i = 1} ^ nw_iに展開されます∑i = 1n個w私このようにして、重みを取り除くことができ、問題は一般的な中央値の問題に変換され、結論は依然として有効です。
#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;
}