POJ2352

     POJ2299:这题其实有两个变量。position 和 value满足position1<position2 而value1>value2的一对数,是逆序的一对数。题目要我们求得是逆序数的总数。我们的求法是归并排序和树状数组。
    在归并排序中,我们其实已经让position变量是由小到大排列的,然后我们要做的就是根据不同的value的值来满足逆序数的条件。 
    然后我用的是树状数组,我用的方法是先离散化,然后按照原先的顺序把值一个个的插入进去,这里按照顺序插入其实我就已经把position的值由小到大排列了,然后我要做的只是根据不同的value的值来求解的(这样,其实我们插入的是value),你插进去之后,只要判断前面有没有值比你小的。因为插入的数的position肯定比前面插入的position要大,你要判断只是值的大小。
    既然是这样,我们也可以直接按照值由小到大的顺序插入,那么我们要做的就是根据位置来判断了(这样,其实我们插入的是position),我们要做的就是求比自己位置小的元素的个数。
    POJ2352:这个题其实和2299这个题是同一个题,2299中的position,value分别对应这个题的x,y。同时条件由position1<position2 而value1>value2 变为x1<=x2,y1<=y2;所以这个题的思路和2299这个题的思路都是一样的。按理说这个题也可以用归并排序,但用起来比较麻烦,在这里,我就用树状数组了。
    思路:先对星星按照x的值由小到大排序,x相等的按照y排序(就是在插入y的时候把x相等,y较小的先插入)。然后我们在插入y的值,因为x已经排好序了,我们要求得就是y之前有多少数已经插入了。这样求得的就是这颗星的等级。
    补充:用数状数组时,我们其实虚构了一个数组B(初始元素都为0,表示没有数插入,有一个数加入就加1,我们求得就是插入的数的个数的总和)。


     结论:树状数组的实现,空间复杂度低,编程复杂度低,容易扩展到多维情况,是一个可以很高效的进行区间统计的数据结构。
               但它的适用范围小,对其可以进行的运算也有限制。比如说如果每次修改的是某一段区间,而非一个元素,维护代价还是相当高的。

  • Source Code
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int NUM = 15005;
    const int MAXSIZE = 32005;
    struct node{
    	int x;
    	int y;
    	friend bool operator<(const node& e1,const node& e2){
    		if(e1.x == e2.x) return e1.y<e2.y;
    			return e1.x<e2.x;
    	}
    };
    node data[NUM];
    int count1[MAXSIZE];
    int degree[NUM];
    int n;
    int max1;
    int lowbit(int l){
    	return l&(-l);
    }
    void update(int l){
    	while(l<=max1){
    		count1[l]+=1;
    		l += lowbit(l);
    	}
    }
    int getSum(int l){
    	int sum = 0;
    	while(l>0){
    		sum+=count1[l];
    		l-=lowbit(l);
    	}
    	return sum;
    }
    int main(){
    	scanf("%d",&n);
    	max1 = 0;
    	memset(count1,0,sizeof(int)*MAXSIZE);
    	memset(degree,0,sizeof(int)*NUM);
    	for(int i =1;i<=n;i++){
    		scanf("%d%d",&data[i].x,&data[i].y);
    		data[i].y+=1;
    		if(data[i].y>max1) max1 = data[i].y;
    	}
    	sort(data+1,data+n+1);
    	for(int i =1;i<=n;i++){
    		degree[getSum(data[i].y)]++;
    		update(data[i].y);
    	}
    	for(int i = 0;i<=n-1;i++){
    		cout<<degree[i]<<endl;
    	}
    	return 0;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值