暑假-树状数组-E - Stars

/*
题意:给出一些星星的横坐标和纵坐标,而且星星的纵坐标按非递减排列,
      如果纵坐标相等,则横坐标按递增排列,任意两颗星星不会重合。
      某一颗星星的level为:这颗星星的左下角(包括x相等但y小,y相等但x小)
	  的星星个数。
思路:设置一个变量m标记它原始的位置,然后按x轴排序,每颗星星的level为:
	  星星原始位置之前(即sum(m-1))的星星个数,每次计算完这颗星星后则在它
	  的原位置标记已经计算过了(即add(m,1))。
*/
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int MAXN=15005;
struct point
{
	int x;//x轴坐标
	int y;//y轴坐标
	int m;//原始位置
};
point a[MAXN];
int c[MAXN],level[MAXN],n;
//树状数组,level数组,星星数量
int lowbit(int x) //树状数组函数之一
{
	return x&(-x);
}
int sum(int i)//树状数组函数之一
{
	int s=0;
	while(i>0)
	{
		s+=c[i];
		i-=lowbit(i);
	}
	return s;
}
void add(int i,int val)//树状数组函数之一
{
	while(i<=n)
	{
		c[i]+=val;
		i+=lowbit(i);
	}
}
bool cmp(point b,point d)//比较函数
{
	if(b.x==d.x)
	{
		return b.y<d.y;
	}
	return b.x<d.x;
}
int main()
{
	 while(scanf("%d",&n)!=EOF)
	 {
		 int ans=0;
		 memset(c,0,sizeof(c));
		 memset(level,0,sizeof(level));
		 for(int i=0;i<n;i++)
		 {
			 scanf("%d%d",&a[i].x,&a[i].y);
			 a[i].m=i+1;//这颗星星的原始位置
		 }
		 sort(a,a+n,cmp);//按x轴排序
		 for(int i=0;i<n;i++)
		 {
			 ans=sum((a[i].m)-1);//计算当前星星的level
			 level[ans]++;//对应的level+1
			 add(a[i].m,1);//标记已经被计算过
		 }
		 for(int i=0;i<n;i++)
		 {
			 printf("%d\n",level[i]);
		 }
	 }
	 return 0;
}

你可能感兴趣的:(树状数组)