poj1990题解

每年,农夫约翰的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;
	}
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值