ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

POJ1990 - MooFest - Indexed Tree求区间和

2021-10-10 10:02:48  阅读:162  来源: 互联网

标签:index 阈值 int Tree 音量 POJ1990 Indexed static 坐标


POJ1990 - MooFest

Description
每年,农场主约翰的N头(1<=N<=20000)奶牛都会参加“MooFest”,这是一个来自世界各地奶牛的社交聚会。
MooFest包括各种各样的活动,包括堆放草包、跳栏、把尾巴钉在农夫身上,当然还有哞哞叫。
当奶牛们排成一队参加某一特定活动时,它们发出的哞哞声几乎震耳欲聋。年复一年地参加这个活动后,有些奶牛实际上失去了一点听力。
每头母牛i都有一个相关的“听力”阈值v(i)(范围为1..20000)。如果一头牛对一头牛i发哞哞声,她必须使用至少是两头牛之间距离v(i)倍的音量,才能被一头牛i听到。
如果两头母牛i和j想要交谈,它们说话的音量必须等于它们之间的距离乘以max(v(i),v(j))。
假设N头奶牛中的每一头都站在一条直线上(每头奶牛在1..20000范围内的某个唯一x坐标处),每对奶牛都在用最可能小的音量进行对话。

计算所有N(N-1)/2对哞哞声产生的所有音量之和。


Input
第1行:整数,N
第2~N+1行:两个整数:牛的听力阈值和x坐标。第2行代表第一头牛;第3行代表第二头牛;等等。
没有两头母牛会站在同一个地方。

Output
第1行:包含一个整数,整数是所有正在交谈的奶牛的音量总和。

Sample Input
4
3 1
2 5
2 6
4 3

Sample Output
57

 


 

思路分析:

以题目所给用例为例:

 

 

1. 如果两头牛i和j想要交谈,它们说话的音量必须等于它们之间的距离乘以max(v(i),v(j)) ==> 当前坐标的牛说话,只有阈值不大于它的牛,才能听见
所以,计算当前牛的音量之和时,需要知道所有比它音量阈值小的牛,那么我们需要按照牛的音量阈值顺序计算;

2. 以坐标3的牛为例:音量之和 = 3左边的音量之和 + 3右边的音量之和
  3左边的音量之和 = ( 3 - 1 )* 4
  3右边的音量之和 = ( 5 - 3 ) * 4 + ( 6 - 3)* 4 = ((5 + 6) - 2 * 3 ) * 4
  以上计算公式时的5+6是3以右的牛的坐标之和,2*3中的2是3以右的牛的个数;
  那么可以分别求出左边和右边的距离,然后统一乘以音量阈值;
  左侧距离和=牛的个数*当前牛的坐标 - 左边坐标之和;右侧距离和=右边坐标之和-牛的个数*当前牛的坐标
  所以,我们需要解决的问题变为:分别求两个区间【0~当前牛的坐标-1,当前牛的坐标+1~最后】内牛的个数之和,牛的坐标之和。

由此,问题变更为求区间和的问题,那么可使用Indexed Tree解决。

 

package tree;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

/**
 * 
 * 
 * 思路:
 * 根据听力阈值排序
 * 按听力阈值顺序遍历
 * 两个indexed tree
 * 一个保存比当前牛听力小的牛的个数,阈值对应的tree1[i]:有牛,则为1,没有则为0(求和)
 * 一个保存比当前牛听力小的牛的坐标,阈值对应的tree2[i]:牛的坐标(求和)
 * 
 * 左侧:query1: 0~当前阈值-1处的tree1之和cntSum,query2:0~当前阈值-1处的tree2之和indexSum
 * 左侧距离和:cntSum*当前牛的坐标-indexSum
 * 右侧:query1:当前阈值+1~最后2*offset-1处的tree1之和cntSum,query2:当前阈值+1~最后2*offset-1处的tree2之和indexSum,
 * 右侧距离和:indexSum-cntSum*当前牛的坐标
 * 
 * 音量总和 = (左侧距离和+右侧距离和)*当前牛的听力阈值
 * 
 * @author XA-GDD
 *
 */
public class POJ1990_MooFest {
	static int N;
	static int _Max_N = 20000;
	static int [][] srcArr = new int[_Max_N][2];
	static int [] cntIdxTree = new int[4*_Max_N];
	static int [] coordIdxTree = new int[4*_Max_N];
	static int offset;
	static long ans = 0;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        while (br.ready()) {
        	st = new StringTokenizer(br.readLine());
        	N = Integer.parseInt(st.nextToken());
        	
        	int maxIndex = 0;
        	for(int i=0;i<N;i++) {
        		st = new StringTokenizer(br.readLine());
        		srcArr[i][0] = Integer.parseInt(st.nextToken());
        		srcArr[i][1] = Integer.parseInt(st.nextToken());
        		maxIndex = Math.max(maxIndex, srcArr[i][1]);
        	}
        	
        	//根据听力阈值排序
        	Arrays.sort(srcArr,0,N, new Comparator<int []>() {
				@Override
				public int compare(int[] o1, int[] o2) {
					return o1[0]-o2[0];
				}
			});
        	
        	//初始化
        	int k=0;
        	while((1<<k)<maxIndex) {
        		k++;
        	}
        	offset = 1<<k;
        	
        	for(int i=0;i<N;i++) {
        		
        		//srcArr[i][0]:音量阈值, srcArr[i][1]:坐标 
        		
        		long [] leftRes = query(offset,offset+srcArr[i][1]-1);
	        	//左侧距离和:牛的个数*当前牛的坐标 - 左边坐标之和
        		long leftDist = leftRes[0]*srcArr[i][1] - leftRes[1];
        		
        		long [] rightRes = query(offset+srcArr[i][1]+1,2*offset-1);
        		//右侧距离和:右边坐标之和 - 牛的个数*当前牛的坐标
        		long rightDist = rightRes[1] - rightRes[0]*srcArr[i][1] ;
        		
        		ans += (leftDist+rightDist) * srcArr[i][0];
        		update(offset+srcArr[i][1],srcArr[i][1]);
        	}
        	
        	System.out.println(ans);
        }
	}
	
	//更新牛的数量及坐标,牛的个数每次都是+1,因此update更新value只传x坐标
	static void update(int index ,int x){
		cntIdxTree[index] += 1;
		coordIdxTree[index] = x;
		index = index >> 1;
		while(index>0) {
			cntIdxTree[index] = cntIdxTree[index*2] + cntIdxTree[index*2+1];
			coordIdxTree[index] = coordIdxTree[index*2] + coordIdxTree[index*2+1];
			index = index >> 1;
		}
	}
	
	//求区间和
	static long[] query(int start ,int end) {
		long count = 0L;
		long coordSum = 0L;
		while(start<=end) {
			if(start%2==1) {
				count += cntIdxTree[start];
				coordSum +=  coordIdxTree[start];
			}
			if(end%2==0) {
				count += cntIdxTree[end];
				coordSum +=  coordIdxTree[end];
			}
			start = ( start + 1 ) >> 1;
			end = ( end - 1 ) >> 1;
		}
		return  new long[] {count,coordSum};
	}

}

  

 

 

标签:index,阈值,int,Tree,音量,POJ1990,Indexed,static,坐标
来源: https://www.cnblogs.com/smile_to_warm/p/15074757.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有