問題描述
FJ有n頭牛,排列成一條直線(不會在同一個點),給出每頭牛在直線上的座標x。另外,每頭牛還有一個自己的聲調v,如果兩頭牛(i和j)之間想要溝通的話,它們必須用同個音調max(v[i],v[j]),溝通起來消耗的能量爲:max(v[i],v[j]) * 它們之間的距離。問要使所有的牛之間都能溝通(兩兩之間),總共需要消耗多少能量。
問題分析
首先將牛按照音調由小到大排序,依次遍歷每頭牛,因爲當前牛的音調最大,所以只需要計算它到其他牛的距離之和。依次計算當前牛和每頭牛的距離肯定會超時,只需分別計算兩邊到當前座標的距離之和就可了。通過樹狀數組維持兩邊點的數量以及兩邊點的座標就可以快速計算出當前座標到其他座標的距離之和。
算法實現
import java.io.*;
import java.util.Arrays;
public class Main {
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out = new PrintWriter(System.out);
int read() throws IOException {
in.nextToken();
return (int) in.nval;
}
public static void main(String[] args) throws IOException {
new Main().solve();
}
int MAXN = 20005;
int INF = 1000000007;
long ans = 0;
int N ;
long[] arr = new long[MAXN];
Pair[] pairs = new Pair[MAXN];
private void solve() throws IOException {
N = read();
for (int i = 0; i < N; i++) {
pairs[i] = new Pair(read(), read());
}
Arrays.sort(pairs, 0, N);
init();
for (int i = 0; i < N; i++) {
long lcnt = sum(bit1, pairs[i].x);
long rcnt = sum(bit1, MAXN) - lcnt;
long lsum = sum(bit2, pairs[i].x);
long rsum = sum(bit2, MAXN) - lsum;
ans += pairs[i].v * (lcnt*pairs[i].x - lsum + rsum - rcnt*pairs[i].x);
add(bit1,pairs[i].x, 1);
add(bit2,pairs[i].x, pairs[i].x);
}
out.println(ans);
out.flush();
}
int[] bit1 = new int[MAXN+1];
int[] bit2 = new int[MAXN+1];
private void init(){
Arrays.fill(bit1,0);
Arrays.fill(bit2,0);
}
private long sum(int[] bit, int i){
long res = 0;
while (i > 0){
res = res + bit[i];
i -= i&-i;
}
return res;
}
private void add(int[] bit, int i, int a){
while (i<=MAXN){
bit[i] += a;
i += i&-i;
}
}
class Pair implements Comparable<Pair>{
int v,x;
public Pair(int v, int x) {
this.v = v;
this.x = x;
}
@Override
public int compareTo(Pair o) {
return v - o.v;
}
}
}