每年,农夫约翰的N(1 <= N <= 20,000)只牛会参加“MooFest”,一个来自世界各地的牛的社交聚会。 MooFest有许多活动,包括干草堆积,篱笆跳跃,把尾巴钉在农夫的身上…当奶牛都站在同一个地方排队,他们会大声喊叫,吼声几乎震耳欲聋。事实上,每年参加了这个活动后,一些奶牛已经失去了部分听力。
每个奶牛具有耳背值v(i)(在1…20,000的范围内)。如果一头牛向牛i吼叫,她必须使用至少是两头母牛之间距离的v(i)倍的声音,以便被牛i听到。如果两个奶牛i和j想要交谈,她们必须以等于她们之间的距离乘以max(v(i),v(j))的音量说话。
假设N头奶牛中的每头奶牛都站在直线上(每头奶牛在1…20,000范围内的某个独特x坐标),每对奶牛都使用尽可能小的声音进行谈话。
计算所有N(N-1)/ 2对正在说话的奶牛产生的所有声音的总和。
Input
*第1行:单个整数,N
*第2到N + 1行:两个整数:牛的耳背值v和x坐标。第2行代表第一头牛;第3行表示第二头牛;等等。没有两头牛会站在同一个位置。
Output
*第1行:仅含单个整数,表示所有牛互相吼叫的所有声音的总和。
Sample Input
4
3 1
2 5
2 6
4 3
Sample Output
57
此题用树状数组求解可以不超时
将牛按v从小到大排序,这样子就不需要对比v的大小,每次出来都是最大的,也就是用当前的v来计算
用两个树状数组,一个是记录当前 i 牛前面(x比当前 i 牛小)有 n 头牛,一个是记录前面站在前面所以牛的总距离 l
因为当前 i 牛的x * n - l 就是站在前面所有牛所用的音量
站在后面的呢?此时还要记录一个总距离m,m - l 就是站在后面的牛的总距离
(m - l)* (i - n - 1)就是与站在后面的牛的音量
这道题一开始确实挺难理解的,慢慢想就懂了
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static long sum(long[] a, int i) {
long res = 0;
while(i > 0) {
res += a[i];
i -= i & -i;
}
return res;
}
public static void add(long[] a, int i, int x) {
while(i <= a.length) {
a[i] += x;
i += i & -i;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
cow[] c = new cow[n];
for(int i = 0; i < n; i++) {
cow t = new cow();
t.v = sc.nextInt();
t.x = sc.nextInt();
c[i] = t;
}
Arrays.sort(c);
long[] a = new long[20000 + 1];//多少头牛在前面
long[] b = new long[20000 + 1];//在前面的牛总距离
long res = 0;
long l = c[0].x;
add(a, c[0].x, 1);
add(b, c[0].x, c[0].x);
for(int i = 1; i < n; i++) {
long num = sum(a, c[i].x);
long lnum = sum(b, c[i].x);
long rnum = l - lnum;
res += (c[i].x * num - lnum) * c[i].v + (rnum - (i - num) * c[i].x) * c[i].v;
add(a, c[i].x, 1);
add(b, c[i].x, c[i].x);
l += c[i].x;
}
System.out.println(res);
}
}
class cow implements Comparable<cow>{
int v, x;
@Override
public String toString() {
return "cow [v=" + v + ", x=" + x + "]";
}
@Override
public int compareTo(cow o) {
return this.v - o.v;
}
}