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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章