POJ 2352 star level

题目链接:

http://poj.org/problem?id=2352

题目大意:
对于每一颗星星来说,都有一个属于自己的level,这个值为其他星星x,y坐标均不大于本星星的个数。输入时按先y由小到大,再x由小到大排列,无相同位置的星星

仔细一想其实这道题目根本不需要用到y,我是反向来思考的,构建一个保存x坐标由0到maxn的线段树,因为最后一个星星肯定不可能x,y同时不大于其他星星,所

以从后面开始看,只计算比它x小或相等的星星的个数,用cnt[ans]++,来记录成为ans水平的个数,再删去这个点,继续找上一个点对应的level

在这里要注意的是数组的范围,我就因为这个改了半天错,第一次发现数组范围定的不够大也是WA

他这里星星个数为15000,但是我们保存的是x的坐标,所以要看x最大达32000,所以用4*32000的大小保存tree[],我的代码里懒得修改了就写成了

#define N 15005
int cnt[N],num[2*N],tree[8*N],D,maxn;//开始我写成的是4*N所以报错T T

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 #define N 15005
 5 int cnt[N],num[2*N],tree[8*N],D,maxn;
 6
 7 int max(int a,int b)
 8 {
 9     return a>b?a:b;
10 }
11
12 void update(int i)
13 {
14     for(;i^1;i>>=1)
15         tree[i>>1]=tree[i]+tree[i^1];
16 }
17
18 int query(int a,int b)
19 {
20     int i=D+a-1,j=D+b+1,ans=0;
21     for(;i^j^1;i>>=1,j>>=1)
22     {
23         if(~i&1) ans+=tree[i^1];
24         if(j&1)  ans+=tree[j^1];
25     }
26     return ans;
27 }
28
29 int main()
30 {
31     int n,x[N],y;
32     while(scanf("%d",&n)!=EOF){
33         maxn=0;
34         memset(num,0,sizeof(num));
35         //memset(tree,0,sizeof(tree));
36         for(int i=1;i<=n;i++){
37             scanf("%d%d",&x[i],&y);
38             maxn=max(maxn,x[i]);
39             num[x[i]]++;
40         }
41         for(D=1;D<maxn+1+2;D<<=1);
42         for(int i=1;i<=maxn+1;i++) tree[D+i]=num[i-1];
43         for(int i=D-1;i>=1;i--) tree[i]=tree[i<<1]+tree[i<<1|1];
44         for(int i=0;i<=n-1;i++) cnt[i]=0;
45         //for(int i=1;i<=2*D-1;i++) printf("%d\n",tree[i]);
46         for(int i=n;i>=1;i--){
47            // printf("%d",query(1,x[i]+1));
48             tree[D+x[i]+1]--;
49             update(D+x[i]+1);
50             cnt[query(1,x[i]+1)]++;
51         }
52         for(int i=0;i<n;i++) printf("%d\n",cnt[i]);
53     }
54     return 0;
55 }

当然从前往后思考也是一样的,那样的话是不断将x添入线段树,这里有一份是学长的代码,果然比我反向思考的要简洁好多,而且从他的代码也得到了其实tree的底层在没有

得到顶点的必要时,也是可以不必强求定位1<<n这种2的几次方的大小的,而在这里正好适用,因为每次找个数和只求到i^j^1即可(这个代表左右子树);

代码如下:

#include <cstdio>
#include <cstring>
const int maxn = 32010;
int tree[maxn<<2],a[maxn];
int N,D;

void update(int i){
    for(;i^1;i >>= 1){
        tree[i>>1] = tree[i]+tree[i^1];
    }
}

int query(int x,int y){
    int i = D+x-1,j = D+y+1,ans = 0;
    for(;i^j^1;i >>= 1,j >>= 1){
        if(~i&1)    ans += tree[i^1];
        if(j&1)     ans += tree[j^1];
    }
    return ans;
}

int main(){
    while(scanf("%d",&N) != EOF){
        memset(tree,0,sizeof(tree));
        memset(a,0,sizeof(a));
        D = 32010;
        for(int i = 0;i < N;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            a[query(1,++x)]++;
            tree[D+x]++;
            update(D+x);
        }
        for(int i = 0;i < N;i++)    printf("%d\n",a[i]);
    }
    return 0;
}

POJ 2352 star level

时间: 2024-12-15 06:15:09

POJ 2352 star level的相关文章

Poj 2352 Star

计算星星的等级,星星左下方的其他星星的数目就是那颗星星的等级(可以在同一水平线或竖直线上),由于y.x是递增给出的,第y层增加减少星星数目对y-1层毫无影响.每增加一颗星星(x,y),只需要统计[1-x]区间星星的数目,就能得到它的level值,另外要更新x之后的数组.算法是用树状数组实现的,也可以用线段树,代码如下: 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 #define Max 320

POJ 2352 star (树状数组)

Language: Default Stars Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 35318   Accepted: 15326 Description Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let

hdu 1541/poj 2352:Stars(树状数组,经典题)

Stars Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4052    Accepted Submission(s): 1592 Problem Description Astronomers often examine star maps where stars are represented by points on a plan

poj 2352 Stars (树状数组)

Stars Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37108   Accepted: 16173 Description Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let the level of a st

POJ 2352 Stars(线段树)

题目地址:POJ 2352 今天的周赛被虐了. . TAT..线段树太渣了..得好好补补了(尽管是从昨天才開始学的..不能算补...) 这题还是非常easy的..维护信息是每个横坐标的出现的次数. 代码例如以下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h>

POJ 2481 Cows &amp;&amp; POJ 2352 Stars(树状数组妙用)

题目链接:POJ 2481 Cows POJ 2352 Stars 发现这两个题目都跟求逆序数有着异曲同工之妙,通过向树状数组中插入点的位置,赋值为1,或者++,然后通过求和来判断比当前 点 "小" 的有多少点. Cows需要自己排序, Stars题目已经给排好序. POJ 2352 Stars 题目大意为在二维坐标上给出一些星星的坐标,求某一个星星左方,下方,左下方的星星个数.题目已经把星星按照Y坐标从小到大,X从小到大排序.因此,在每次对一个星星进行统计时,之前出现过的星星,只要X

POJ - 2352 - Stars

题目链接:POJ - 2352 题目大意: 给你N个星星的坐标,问每个星星的左下角有几颗星星. 注意输入坐标y是按递增输入的. 题目分析: 算是树状数组的一个基础题目吧,有些题目也是以这道题为基础的. 直接运用数组数组即可,具体看代码. 不过注意由于x坐标有可能是0,所以要对所有的X坐标加一(不要忘了区间上界也要增大一个), 防止add()函数出现死循环超时. 给出代码: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cs

poj 2352 Stars 数星星 详解

题目: poj 2352 Stars 数星星 题意:已知n个星星的坐标.每个星星都有一个等级,数值等于坐标系内纵坐标和横坐标皆不大于它的星星的个数.星星的坐标按照纵坐标从小到大的顺序给出,纵坐标相同时则按照横坐标从小到大输出. (0 <= x, y <= 32000) 要求输出等级0到n-1之间各等级的星星个数. 分析: 这道题不难想到n平方的算法,即从纵坐标最小的开始搜,每次找它前面横坐标的值比它小的点的个数,两个for循环搞定,但是会超时. 所以需要用一些数据结构去优化,主要是优化找 横坐

POJ 2352

第一题树状数组 模板题 #include <cstdio> #include <iostream> using namespace std; int c[32002],lv[15002],n; int lowbit(int x){return x&(-x);} int sum(int b){ int sum=0; while(b>0){ sum+=c[b]; b-=lowbit(b); } return sum; } void add(int x){ while(x&