poj 2352 Stars 树状数组or线段树

来源:互联网 发布:比较好的耳机 知乎 编辑:程序博客网 时间:2024/05/21 22:26

题目大意:
在坐标上有n个星星,如果某个星星坐标为(x, y), 它的左下位置为:(x0,y0),x0<=x 且y0<=y。如果左下位置有a个星星,就表示这个星星属于level x
按照y递增,如果y相同则x递增的顺序给出n个星星,求出所有level水平的数量。

分析:
因为输入是按照按照y递增,如果y相同则x递增的顺序给出的, 所以,对于第i颗星星,它的level就是之前出现过的星星中,横坐标x小于等于i星横坐标的那些星星的总数量(前面的y一定比后面的y小)。
所以,需要找到一种数据结构来记录所有星星的x值,方便的求出所有值为0~x的星星总数量。
树状数组和线段树都是很适合处理这种问题。

树状数组:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int N=32005;int c[N],level[N];int lowbit(int x){return x&(-x);}int getsum(int x){    int sum =0;    for(int i=x;i>0;i-=lowbit(i))sum+=c[i];    return sum;}void add(int x){    for(int i=x;i<N;i+=lowbit(i))c[i]++;}int main(){    int n,x,y;    while(~scanf("%d",&n)){        memset(level,0,sizeof(level));        memset(c,0,sizeof(c));        for(int i=0;i<n;i++){            scanf("%d%d",&x,&y);            ++x;            level[getsum(x)]++;            add(x);        }        for(int i=0;i<n;i++)            printf("%d\n",level[i]);    }    return 0;}

线段树:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int N=15005;const int M=32009;int sum[M<<2];int level[N];void pushup(int rt){    sum[rt]=sum[rt<<1]+sum[rt<<1|1];}int query(int a,int b,int l,int r,int rt){    if(a<=l&&r<=b)return sum[rt];    int m=(l+r)>>1;    int ans=0;    if(a<=m)ans=query(a,b,lson);    if(b>m)ans+=query(a,b,rson);    return ans;}void update(int x,int l,int r,int rt){    if(l==r){sum[rt]++;return;}    int m=(l+r)>>1;    if(x<=m)update(x,lson);    else update(x,rson);    pushup(rt);}int main(){    int n,x,y;    scanf("%d",&n);        memset(sum,0,sizeof(sum));        memset(level,0,sizeof(level));        for(int i=0;i<n;i++){            scanf("%d%d",&x,&y);            int t=query(0,x,0,M,1);            level[t]++;            update(x,0,M,1);        }        for(int i=0;i<n;i++)            printf("%d\n",level[i]);    return 0;}
0 0
原创粉丝点击