题意:按y递增的顺序给出n颗星星的坐标(y相等则x递增),每个星星的等级,等于在它左边且在它下边(包括水平和垂直方向)的星星的数量,求出等级为0到n-1的星星分别有多少个。
分析:树状数组或者线段树。
//416K 141MS 树状数组
#include <stdio.h>
#include <string.h>
#define MAX 32010
int c[MAX] ; //树状数组
int lev[MAX] ; //level[X] 指的是 不超过当前点的高度和不在当前点右边的点的个数为x 的这些点的个数
int Low_Bit ( int x )
{
return x & ( -x ) ;
}
void Update ( int x ) //插入一个 x 就要更新 x 的祖先们
{
while ( x < MAX )
{
c[x] ++ ;
x += Low_Bit ( x ) ;
}
}
int Get_Sum ( int x ) //求得 x 的等级 ,也就是 x 前面有多少个和x同列或者靠左的点
{
//因为输入的时候,y是递增的,所以不用考虑y
int sum ;
sum = 0 ;
while ( x > 0 )
{
sum += c[x] ;
x -= Low_Bit ( x ) ; //x 前面的一棵子树的根的下标
}
return sum ;
}
int
main ( )
{
int n ;
while ( EOF != scanf ("%d" , & n ) )
{
memset ( lev , 0 , sizeof ( lev ) ) ;
memset ( c , 0 , sizeof ( c ) ) ;
int i ;
for ( i = 1 ; i <= n ; i ++ )
{
int x , y ;
scanf ("%d%d" , & x , & y ) ;
x ++ ;
int index ;
index = Get_Sum ( x ) ;
lev[index] ++ ;
Update ( x ) ;
}
for ( i = 0 ; i < n ; i ++ )
{
printf ("%d\n" , lev[i] ) ;
}
}
return 0 ;
}
线段树的做法是,每插入一颗星星(设其横坐标为x),将区间[x,32000]加1,即后面的星星的层数加1,这样后面的星星调用Query(x)便可返回层数.
//1000K 219MS
#include <stdio.h>
#define L(X) ((X)<<1)
#define R(X) ((X<<1)|1)
#define MID(X,Y) ((X+Y)>>1)
#define N 32005
#define DEBUG puts("Hi") ;
int lev[N] ;
struct node
{
int left , right ;
int val ;
}node[N*4];
void Creat_Tree ( int const left , int const right , int const n )
{
node[n].left = left ;
node[n].right = right ;
node[n].val = 0 ;
if ( left < right )
{
int mid ;
mid = MID (left , right ) ;
Creat_Tree ( left , mid , L(n) ) ;
Creat_Tree ( mid + 1 , right , R(n) ) ;
}
}
void Update ( int const left , int const right , int const n )
{
if ( node[n].left == left && node[n].right == right )
{
node[n].val ++ ;
}
else
{
int mid ;
mid = MID ( node[n].left , node[n].right ) ;
if ( right <= mid )
{
Update ( left , right , L(n) ) ;
}
else if ( left > mid )
{
Update ( left , right , R(n) ) ;
}
else
{
Update ( left , mid , L(n) ) ;
Update ( mid + 1 , right , R(n) ) ;
}
}
}
int Query ( int x , int n )
{
if ( node[n].right == node[n].left )
{
return node[n].val ;
}
else
{
int mid ;
mid = MID ( node[n].left , node[n].right ) ;
if ( x <= mid )
{
return node[n].val + Query( x , L(n) ) ;
}
else
{
return node[n].val + Query( x , R(n) ) ;
}
}
}
int
main ( )
{
int n ;
scanf ("%d" , & n ) ;
Creat_Tree ( 0 , N , 1 ) ;
int i ;
for ( i = 0 ; i < n ; i ++ )
{
int x , y ;
scanf ("%d%d" , & x , & y ) ;
int index ;
index = Query ( x , 1 ) ;
lev[index] ++ ;
Update ( x , N , 1 ) ;
}
for ( i = 0 ; i < n ; i ++ )
{
printf ("%d\n" , lev[i] ) ;
}
return 0 ;
}