HDU1541 经典树状数组

HDU1541

题意:

如图,等级为0的点有1,等级为1得点有4,2  等级为2的点有3,等级为3的点有5-------即即左下角的点的个数

现给你一些点(x,y),输入顺序按y升序,y相等时按x升序排列

请分别输出等级0---n-1的点的个数

分析:

暴力超时TEL,用g++提交也超时

#include<iostream>
#include<cstring>
#include<cstdio>
#include "cstring"
using namespace std;
int a[15005];
int c[15005];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int x,cnt=0;
        memset(c,0,sizeof(c));
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&a[i],&x);
            for(int j=0;j<i;j++)
                if(a[j]<=a[i])
                cnt++;///属于哪个水平?
            c[cnt]++;
            cnt=0;
        }
        for(int i=0;i<n;i++)
        {
            printf("%d
",c[i]);
        }
    }
    return 0;
}

再分析

只统计之前小于等于x的点的个数,即可确定等级

统计个数,需用到求和,用树状数组

#include "cstdio"
#include "cstring"
#include "iostream"
using namespace std;
int c[32000+5];///下标代表x值,值代表个数
int a[32000+5];///下标代等级,值代表个数
int lowbit(int x)
{
    return x&(-x);
}
void update(int i,int plus)
{
    while(i<=32005)
    {
        c[i]+=plus;
        i+=lowbit(i);
    }
}
int getSum(int x)
{
    int s=0;
    while(x>0)
    {
        s+=c[x];
        x-=lowbit(x);
    }
    return s;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)///确定一个等级,统计小于x的个数
    {
        int x,y;
        memset(a,0,sizeof(a));
        memset(c,0,sizeof(c));
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            a[getSum(x+1)]++;///等级确定=统计c(1->x)个数
            update(x+1,1);///c 对应x +1
        }
        for(int i=0;i<n;i++)
        {
            printf("%d
",a[i]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/kimsimple/p/6729027.html