51 Nod 1110距離之和最小V3
阿新 • • 發佈:2018-11-01
1110 距離之和最小 V3
- 1 秒
- 131,072 KB
- 40 分
- 4 級題
X軸上有N個點,每個點除了包括一個位置資料X[i],還包括一個權值W[i]。點P到點P[i]的帶權距離 = 實際距離 * P[i]的權值。求X軸上一點使它到這N個點的帶權距離之和最小,輸出這個最小的帶權距離之和。
收起
輸入
第1行:點的數量N。(2 <= N <= 10000) 第2 - N + 1行:每行2個數,中間用空格分隔,分別是點的位置及權值。(-10^5 <= X[i] <= 10^5,1 <= W[i] <= 10^5)
輸出
輸出最小的帶權距離之和。
輸入樣例
5 -1 1 -3 1 0 1 7 1 9 1
輸出樣例
20
由於最右端點-最左端點的距離最大不會超過200000,一次從左往右掃一遍,在過程中維護兩個集合:在當前位置左邊的點,和在當前位置右邊的點。走的時候更新ans即可。詳情如下:
#include<bits/stdc++.h> #include<stdio.h> #include<iostream> #include<cmath> #include<math.h> #include<queue> #include<set> #include<map> #include<iomanip> #include<algorithm> #include<stack> using namespace std; #define inf 0x3f3f3f3f typedef long long ll; int N; int x[10005]; int w[10005]; int id[10005]; bool cmp(int i,int j) { return x[i]<x[j]; } ll L,R; ll ans=0x3f3f3f3f3f3f3f3f; int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif // ONLINE_JUDGE scanf("%lld",&N); for(int i=0;i<N;i++){scanf("%d%d",&x[i],&w[i]);R+=w[i];} for(int i=0;i<N;i++)id[i]=i; sort(id,id+N,cmp); int pos=x[id[0]]; int now=1; ll pre=0; for(int i=1;i<N;i++) { pre+=1ll*(x[id[i]]-pos)*w[id[i]]; } ll current=0; L=w[id[0]];R-=w[id[0]]; for(;pos<=x[id[N-1]];) { current=pre+L-R; pos++; ans=min(ans,current); pre=current; if(pos==x[id[now]]) { L+=w[id[now]]; R-=w[id[now]]; now++; } } printf("%lld\n",ans); return 0; }