HDU OJ 4325 Flowers 【树状数组离散化】

原题连接:http://acm.hdu.edu.cn/showproblem.php?pid=4325

题意:给n朵花,每朵花都有一个开花时间(是一个区间),给q次查询命令,每次查询输入一个时间点,询问该时刻共有多少花正在开……

思路:这就是一个树状数组的  插线问点 算法,但是 注意  范围1 <= Si <= Ti <= 10^9   数组是开不下的,而且n,q 的范围比较小,这就说明要先对数据进行离散化处理,缩小范围即可。。但是怎么离散化呢?首先我们 看题,查询是离线的,我们可以将开花的时间区间和查询一次全部离散化了,这样就不影响最终结果了。

首先我们在输入每组数据是要记录编号,记录在flo 中(即输入顺序)    -----参考代码 P1 处

然后我们根据num 值的大小对结构体排序    

接着我们通过访问编号将num值离散化,注意可能有重复的num,保存在 AC[i]=j数组中,i是输入时的编号,j是离散后的数值。 ------P2

最后通过编号在树状数组ans中插线,然后问点。-----P3

AC代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int Max=110000;
int AC[Max],ans[Max];
struct hello
{
    int num;
    int id;

}flo[Max];
int lowbit(int i)
{
    return i&(-i);
}
void update(int x,int y)
{
    while(x<Max)
    {
        ans[x]+=y;
        x+=lowbit(x);
    }
}
int find(int x)
{
    int sum=0;
    while(x>0)
    {
        sum+=ans[x];
        x-=lowbit(x);
    }
    return sum;
}
bool cmp(hello t1,hello t2)
{
    return t1.num<t2.num;
}
int main()
{
    int i,j,n,m,ncase,q;
    scanf("%d",&ncase);
    for(m=1;m<=ncase;m++)
    {
        int s,t,cnt=0;
        printf("Case #%d:\n",m);
        memset(ans,0,sizeof(ans));
        memset(AC,0,sizeof(AC));
        scanf("%d%d",&n,&q);
        for(i=0;i<2*n+q;i++)
        {
            scanf("%d",&flo[i].num);         //------P1
            flo[i].id=i;
        }
        sort(flo,flo+2*n+q,cmp);
        for(i=0;i<2*n+q;i++)
        {
            if(i==0||flo[i].num!=flo[i-1].num)    //--------P2
                    AC[flo[i].id]=++cnt;
            else
                  AC[flo[i].id]=cnt;
        }
        for(i=0;i<2*n;i+=2)                   //--------P3
        {
            update(AC[i],1);
            update(AC[i+1]+1,-1);
        }
        for(i=2*n;i<2*n+q;i++)
           printf("%d\n",find(AC[i]));
    }
}



发布了81 篇原创文章 · 获赞 184 · 访问量 18万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章