您的位置:首页 > 其它

poj 2352 Stars (线段树#4/树状数组)

2012-08-16 11:43 387 查看
本质上是维护一个表,每次改变一个元素的值,然后求前i个元素的和。

法一:线段树

我本来是想每个叶节点表示从1到该节点位置的元素和,插入一个元素,那么它后面的节点的值都要加一,这便是操作区间。可是我这样是复杂化了,无限WA。

其实就是简单的求和问题,每个节点维护一个sum值就好了。

代码:454ms



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

#define N 15009 
#define L 32010 

struct node{
       int l, r;
       int val;
    }Tree[L * 5];
///

int n;
int level
;

void build(int l, int r, int x)
{
     Tree[x].l = l;
     Tree[x].r = r;
     Tree[x].val = 0;
     if (l == r)return;
     int mid = (l + r) / 2;
     build(l, mid, x * 2);
     build(mid + 1, r, x * 2 + 1);
}

void update(int nu,  int x)
{
       if (Tree[x].l <= nu && nu <= Tree[x].r)
       {
                Tree[x].val++; 
       }
       if (Tree[x].l == Tree[x].r)return; 
       int mid = (Tree[x].l + Tree[x].r) / 2;
       if (mid < nu)update(nu, x * 2 + 1);
       else if (mid >= nu)update(nu,  x * 2);
} 

int find(int l, int r,  int x)
{ 
       if (Tree[x].l == l && Tree[x].r == r)
       {
                     return Tree[x].val;
       }
       int mid =  (Tree[x].l + Tree[x].r) / 2;
       if (mid < l)return find(l, r, x * 2 + 1);
       if (mid >= r)return find(l, r, x * 2);
       return find(l, mid, x * 2) + find(mid + 1, r, x * 2 + 1); 
}
   

 

int main()
{
   // FILE* fp = fopen("in.txt", "r"); 
    scanf(  "%d", &n); 
    build(0, L, 1);
    for (int i = 0; i < n; i++) level[i] = 0;
    int x, y; 
    for (int i = 0; i < n; i++)
    {
          scanf( "%d %d", &x, &y);
          level[find(0, x, 1)]++;
          update(x, 1); 
    }
    for (int i = 0; i < n; i++)
         printf("%d\n", level[i]); 
  //  getchar();
    return 0;
}


法二:树状数组

树状数组应用范围较窄,“改变一个元素,求前i个元素的和”。

391ms



#include <cstdio>
#include <cstdlib>
#include <cstring> 
using namespace std;
#define N 32010
    int n, c
, level
;

inline int lowbit(int x)
{
      return x & (-x);
}

int sum(int x)
{
     int ans = 0;
     while (x > 0)
     {
           ans += c[x];
           x -= lowbit(x);
     } 
     return ans;
} 

void update(int i)
{
     while (i <= N)
     {
           c[i] ++;
           i += lowbit(i);
     } 
}
 
int main()
{
      int x, y;
      scanf("%d", &n);
      memset(c, 0, sizeof(c));
      memset(level, 0, sizeof(level)); 
      for (int i = 0; i < n; i++)
      {
            scanf("%d %d", &x, &y);
            level[sum(x + 1)]++;
            update(x + 1);
      }
      for (int i = 0; i < n; i++)printf("%d\n", level[i]);
     // scanf("%d", &n); 
      return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: