hdu1541 Stars

来源:互联网 发布:鬼子来了结局知乎 编辑:程序博客网 时间:2024/06/05 23:30

这是一道可以用线段树做的题目,题目大意是计算某一刻星星坐标左下方的星星数(自己没有被包括),很明显的线段树,由于输入数据已经保证y坐标是按照递增顺序输出的,那么可以对每一个y,将其x打成一棵线段树,然后依次找出[0,x[i]]之间的cover值就可以了,要注意一下是先计算当前x[i]的cover值后在将x插入线段树。因为自己这个点不被计算到星星等级中。。。这题用树状数组空间时间都要省很多。。。

#include <iostream>
using namespace std;
const int size = 15000;
struct STree
{
       int l, r;
       int cover;      
}stree[6*size+10];

void creat(int num, int l, int r)
{
     stree[num].l = l, stree[num].r = r, stree[num].cover = 0;
     if (l == r) return ;
     int mid = (l+r)>>1;
     int p = num << 1;
     creat(p, l, mid);
     creat(p+1, mid+1, r);
}

void insert(int num, int l, int r)
{
     int a = stree[num].l, b = stree[num].r;
     int mid = (a+b) >> 1;
     int p = num << 1; 
     if (l == a && r == b){
        stree[num].cover ++; 
        return ;  
     }  
     if (r <= mid){
        insert(p, l, r);     
     }
     else
         if (l > mid)insert(p+1, l, r);
         else {
              insert(p, l, mid);
              insert(p+1, mid+1, r);    
         }
     stree[num].cover = stree[p].cover + stree[p+1].cover;
}

int find1(int num, int l, int r)
{
     int a = stree[num].l, b = stree[num].r;
     int mid = (a+b) >> 1;
     int p = num << 1; 
     int ll = 0, rr = 0;
     if (l <= a && r >= b){
        return stree[num].cover;    
     }  
     if (r <= mid)ll= find1(p, l, r);
     else
     if (l > mid)rr= find1(p+1, l, r);
     else {
          ll = find1(p, l, mid);
          rr = find1(p+1, mid+1, r);
     }
     return ll+rr;
}
int ligh[size+10];
int n;
int x[size+10], y;
int main()
{
   
    while (scanf("%d", &n) != EOF){
          int left = INT_MAX, right = INT_MIN;
          for (int i = 0; i < n; i ++){
              scanf("%d%d", &x[i], &y);
              if (x[i] < left)left = x[i];
              if (x[i] > right)right = x[i];
          }  
          creat(1, left, right);
          for (int i = 0; i < n; i ++)ligh[i] = 0;
          for (int i = 0; i < n; i ++){
              ligh[find1(1, 0, x[i])] ++;//注意是先计算再插入
              insert(1, x[i], x[i]);
          }
          for (int i = 0; i < n; i ++){
              printf("%d\n", ligh[i]);   
          }
    }
    return 0;   
}

树状数组版:

#include <iostream>
using namespace std;
const int size = 32010;
const int N = 15010;
int x;
int tree[size];
int ligh[N];
int lowbit(int x)
{
    return x&(x^(x-1));   
}
void insert(int k)
{
     while (k <= size){
           tree[k] ++;
           k += lowbit(k);     
     }
}
int find1(int k)
{
     int sum = 0;
     while (k >= 1){
           sum += tree[k];
           k -= lowbit(k);
     }    
     return sum;
}
int main()
{
    int n, y;
    while (scanf("%d", &n) != EOF){
          for (int i = 0; i < n; i ++)ligh[i] = 0;
          memset(tree, 0, sizeof(tree));
          for (int i = 0; i < n; i ++){
              scanf("%d%d", &x, &y);
              ligh[find1(x+1)] ++;
              insert(x+1);
          }  
          for (int i = 0; i < n; i ++){
              printf("%d\n", ligh[i]);   
          }
    }
    return 0;   
}