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,我们求得就是插入的数的个数的总和)。
在归并排序中,我们其实已经让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; }