树状数组训练A题

虽说已经做了不少题了,但是每次回顾的时候都找不回当初的一些思路。

最后还是觉得写博客比较好,做完一道题写一篇博客来理清思,复习的时候也可以更加直观。


题目来源 POJ2481 Cows;

Cows
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 6854 Accepted: 2211

Description

Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in his field is particularly good. 

Farmer John has N cows (we number the cows from 1 to N). Each of Farmer John's N cows has a range of clover that she particularly likes (these ranges might overlap). The ranges are defined by a closed interval [S,E]. 

But some cows are strong and some are weak. Given two cows: cow i and cow j, their favourite clover range is [Si, Ei] and [Sj, Ej]. If Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj, we say that cow i is stronger than cow j

For each cow, how many cows are stronger than her? Farmer John needs your help!

Input

The input contains multiple test cases. 
For each test case, the first line is an integer N (1 <= N <= 10 5), which is the number of cows. Then come N lines, the i-th of which contains two integers: S and E(0 <= S < E <= 10 5) specifying the start end location respectively of a range preferred by some cow. Locations are given as distance from the start of the ridge. 

The end of the input contains a single 0.

Output

For each test case, output one line containing n space-separated integers, the i-th of which specifying the number of cows that are stronger than cow i

Sample Input

3
1 2
0 3
3 4
0

Sample Output

1 0 0
 
题目大意大概是讲:给出N头牛,每头牛都有自己吃的草的范围[S,E];然后有这样的规定 如果两头牛 i,j。Si小于Sj且Ei大于Ej。就说明牛i比牛j强。
最后输出对于所有的牛,比它强的有多少。
 
说实话,我比较蠢,讨论班里熊学长讲的东西除了一开始的概念以外,我都没听懂。。。所以这套题过了半星期都没动手做。
昨天晚上好像比较闲,就研究了下。结果是。。。。还是不懂。
虽然树状数组的概念懂了,但是做题的时候就不会往上面靠了。
所以我先去做了下Star(poj 2352)。做完后终于有些思路。
画出图就可看出,若以S为横轴,E为纵轴,除了本题求的是左上角的数目,就变成了和Star一样了。

首先是对牛进行排序,将E降序排序,E相同则将S升序排序。
排完序后,对于排在前面的cow的sum(cow.S)定然是左上角的数目。
 
这一点我一开始是没想明白的!
因为这里sum计算的是比cow.S小的和,和cow.E无关!
而先排了降序E,保证了计算sum(cow.S)时,前面的cow i不会对后面牛的S比它的S小的产生影响!
 
注意的一点是,题目要求按牛的顺序输出答案,我一开始只想到了把各个和求完后,再按照id排序一遍输出,但是感觉实现起来不大对劲
参考他人题解才发现可以用一个数组存储答案,即 res[cow.id]这样存储。这样就不会出现我之前想的尴尬的场景;
代码如下:
package FenwickTree;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.*;
class cow implements Comparable<cow>{
	int l,r,d;
	int n=0;
	cow(int l,int r,int d){
		this.l=l;
		this.r=r;
		this.d=d;
		
	}
	@Override
	public int compareTo(cow o) {
		
		if(this.r==o.r)return this.l-o.l;
		else return o.r-this.r;
		
	}
	
}
public class Main{
	
    static StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
   static int nextInt() throws IOException{
	   in.nextToken();
	   return (int) in.nval;
   }
   static long nextLong() throws IOException{
	   in.nextToken();
	   return (long)in.nval;
   }
   static double nextDouble () throws IOException{
	   in.nextToken();
	   return in.nval;
   }
   static String next() throws IOException{
	   in.nextToken();
	   return in.sval;
   }
    static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));

	static int c[]=new int [100086];
	static int []res =new int [100086];
	static int N;
	static int lowbit(int i){
		return i&(-i);
	}
	static int sum(int i){
		int sum=0;
		while(i>0){
			sum+=c[i];
			i-=lowbit(i);
		}
		return sum;
	}
	static void add(int i){
		while(i<100086){
			c[i]++;
			i+=lowbit(i);
		}
	}
	static cow cows[] =new cow[100086];
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		//Scanner sc =new	Scanner (System.in);
		while(true){
			N=nextInt();
			if(N==0)break;
			Arrays.fill(res,0);
			Arrays.fill(c, 0);
			for(int i=0;i<N;i++){
				int x=nextInt()+1;
				int y=nextInt()+1;
				cows[i]=new cow(x,y,i);
			}
			Arrays.sort(cows,0,N);
			res[cows[0].d] = sum(cows[0].l); 
	        add(cows[0].l);  
			for(int i=1;i<N;i++){
				if(cows[i-1].l==cows[i].l&&cows[i-1].r==cows[i].r)res[cows[i].d]=res[cows[i-1].d];
				else res[cows[i].d]=sum(cows[i].l);
				add(cows[i].l);
			}
		//	Arrays.sort(cows);
			for(int i=0;i<N-1;i++){
				out.print(res[i]+" ");
			}	
			out.println(res[N-1]);
			out.flush();
		
		}
	}

}


 
 
 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值