poj2352stars 点线段树和树状数组


题意:给星星的坐标,定义每个星星左下角(包括正左边和正上方)的星星数是它的level,统计各个level的星星数。

分析:乍看是个二维的统计,因为数据给出的是 y坐标升序,y相等 x坐标升序,所以可以一次读入数据,只要统计 x左边的星星数就行了,

        这道题很好的启示就是二维降一维的方法————按某种规则排序。

下面给出了线段树和树状数组的写法。

点线段树cpp代码如下:


#include <cstdio>
#include 
<algorithm>
using namespace  std;

const int root = 0
;
struct
 Node{
       
int
 l,r,cnt;
       
int
 lnd,rnd;
}node[
60005
];
int
 cnt,cntx;
int indx[15010
];
int x[15010],y[15010
];


void Creat(int p,int l,int
 r)
{
     node[p].l 
= l; node[p].r =
 r;
     node[p].cnt 
= 0
;
     
if (l <
 r)
     {
           
int mid = (l + r) >> 1
;
           node[p].lnd 
= ++
cnt;
           Creat(cnt,l,mid);
           node[p].rnd 
= ++
cnt;
           Creat(cnt,mid
+1
,r);
     }
     
else {node[p].lnd = node[p].rnd = -1
;}
}

void upData(int
 p)
{
     
if (node[p].l <
 node[p].r)
        node[p].cnt 
= node[node[p].lnd].cnt +
 node[node[p].rnd].cnt;
}

void Insert(int p,int
 id)
{
     
if (id == node[p].l && id ==
 node[p].r)
         node[p].cnt
++
;
     
else
 {
            
int mid = (node[p].l + node[p].r) >> 1
;
            
if (mid <
 id)
               Insert(node[p].rnd,id);
            
else
 Insert(node[p].lnd,id);
          }
     upData(p);
}

int  query(int p,int l,int
 r)
{
     
int ans = 0
;
     
if (l <= node[p].l && node[p].r <=
 r)
        ans 
=
 node[p].cnt;
     
else
{
          
int mid = (node[p].l + node[p].r) >> 1
;
          
if (mid >=
 l)
             ans 
+=
 query(node[p].lnd,l,r);
          
if (mid <
 r)
             ans 
+=
 query(node[p].rnd,l,r);
         }
     
return
 ans;
}
int Bi_Search(int
 key)
{
    
int l = 1,r = cntx+1
,mid;
    
while (l <
 r)
    {
          mid 
= (l + r) >> 1
;
          
if (indx[mid] ==
 key)
             
return
 mid;
          
else if (indx[mid] <
 key)
                  l 
= mid + 1
;
              
else r =
 mid;
    }
}

void
 Init_Index()
{
     sort(indx
+1,indx+1+
cntx);
   
//
  for (int i = 1; i <= cntx; i++)
  
//       printf("%d,",indx[i]);

     int m = 1
     
for (int i = 2; i <= cntx; i++
)
     {
         
         
if (indx[i] != indx[i-1
])
         {
            m
++
;
            indx[m] 
=
 indx[i];
         }
     }
         
     cntx 
=
 m;
}

int
 main()
{
    
int
 n,i,j,k,id;
    
int count[15010
];
    
while (scanf("%d",&n) !=
 EOF)
    {
          
for (i = 1; i <= n; i++
)
          {
              count[i] 
= 0
;
              scanf(
"%d %d",&x[i],&
y[i]);
              indx[i] 
=
 x[i];
          }
         
//
 for (i = 1; i <= n ;i++)
        
//
      printf("%d ",indx[i]);
        
//  printf("\n");

          cntx =  n; 
          Init_Index();
       
/*
   for (i = 1; i <= cntx; i++)
              printf("%d ",indx[i]);
           printf("cntx = %d\n",cntx);
*/

          cnt 
= 0 ;
          Creat(root,
1
,cntx);
          
for (i = 1; i <= n; i++
)
          {
              id 
=
 Bi_Search(x[i]);
            
//  printf("id = %d\n",id);

              k = query(root,1 ,id);
            
//  printf("i = %d,k = %d\n",i,k);

              count[k] ++ ;
              Insert(root,id);
          }
          
for (i = 0; i < n; i++
)
              printf(
"%d\n"
,count[i]);
          
    }
    
return 0
;
}



树状数组的cpp代码:

#include<stdio.h>
int a[32002 ];
int level[15000
];
int
 N;
int lowbit(int
 n){
    
return n&(-
n);
}
int Sum(int
 n)
{
    
int result = 0
;
    
while(n!=0
){
        result
+=
a[n];
        n
-=
lowbit(n);
    }
    
return
 result;
}
void Update(int
 n)
{
    
while(n<=32001
){
        a[n]
++
;
        n
+=
lowbit(n);
    }
}
void
 init()
{
    
int
 i;
    
for(i=0;i<=N;i++
)
        level[i]
=a[i]=0
;
}
int
 main()
{
    
int
 x,y,i;
    scanf(
"%d",&
N);
    i
=
N;
    init();
    
while(i--
){
        scanf(
"%d %d",&x,&
y);
        level[Sum(x
+1)]++
;
        Update(x
+1
);
        
    }

    
for(i=0;i<N;i++
)
        printf(
"%d\n"
,level[i]);
}

你可能感兴趣的:(poj2352stars 点线段树和树状数组)