pku2352: Stars

pku2352: http://poj.org/problem?id=2352
题意:给出星星的坐标,问每一层次n有多少个星星:星星a的左边或下边共有x个星星,则a属于层次x,ans[x]++,求ans[0]~ans[n-1]
解法1:线段树:从给出的坐标的顺序可知后面的坐标不会影响的前面的坐标,所以可以边输入边计算。首先建树,再从点1开始往下搜,若所求点d在树的左子树,继续往下搜,若在树的右子树,加上左子树的数目(左子树的点都小于d),再搜右子树,遇到左端点a与右端点b相同的情况,此时a=b=d,更新点,加一。
code1:
#include<iostream>
#include<cstdio>
#include<cstdlib>
struct abc
{
    int l,r,cnt;
}v[33000*4];
int ans[16000];
void build(int s,int t,int k)         //建树
{
    v[k].l=s;
    v[k].r=t;
    v[k].cnt=0;
    if(s==t)
        return;
    int mid=(s+t)/2;
    build(s,mid,k*2);
    build(mid+1,t,k*2+1);
}
int solve(int d,int k)
{
    if(v[k].l==v[k].r)         //l=r=d
        return ++v[k].cnt;     //更新点
    else
    {
        int x=0;
        if(d<=v[k*2].r)
            x=solve(d,k*2);
        else
            x=v[k*2].cnt+solve(d,k*2+1);
        v[k].cnt=v[k*2].cnt+v[k*2+1].cnt;    //点往上更新
        return x;          //返回所求点左下点以及本身点的个数
    }
}
int main()
{
    int n,x,y;
    while(scanf("%d",&n)!=EOF)
    {
        memset(ans,0,sizeof(ans));
        build(0,32000,1);
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            ans[solve(x,1)-1]++;
        }
        for(int i=0;i<n;i++)
            printf("%d\n",ans[i]);
    }
}
/*input:
5
1 1
5 1
7 1
3 3
5 5
output:
1
2
1
1
0*/
解法2:树状数组:对于节点i,其父节点为i+i&(-i),其前一棵树为i-i&(-i),先初始化每个点为0,再求前x项和即可
code2:

#include<iostream>
#include<cstdio>
#include<cstdlib>
int ans[32010],v[32010];
int lowbit(int x)          //求最小幂2^k
{
    return x&(-x);
}
int sum(int x)             //求前n项和
{
    int s=0;
    while(x>0)
    {
        s=s+v[x];
        x=x-lowbit(x);
    }
    return s;
}
void update(int x)            //对某个元素进行加法操作
{
    while(x<32010)
    {
       v[x]++;
       x=x+lowbit(x);
    }
}
int main()
{
    int n,x,y;
    while(scanf("%d",&n)!=EOF)
    {
        memset(ans,0,sizeof(ans));
        memset(v,0,sizeof(v));
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            ans[sum(x+1)]++;           //树状数组是从1开始的
            update(x+1);
        }
        for(int i=0;i<n;i++)
            printf("%d\n",ans[i]);
    }
}
/*input:
5
1 1
5 1
7 1
3 3
5 5
output:
1
2
1
1
0*/

 


posted on 2012-08-05 11:41  acmer-jun  阅读(185)  评论(0编辑  收藏  举报

导航