1. 程式人生 > >hdu4325-Flowers-樹狀陣列+離散化

hdu4325-Flowers-樹狀陣列+離散化

Flowers

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3687    Accepted Submission(s): 1821


Problem Description As is known to all, the blooming time and duration varies between different kinds of flowers. Now there is a garden planted full of flowers. The gardener wants to know how many flowers will bloom in the garden in a specific time. But there are too many flowers in the garden, so he wants you to help him.  

 

Input The first line contains a single integer t (1 <= t <= 10), the number of test cases.
For each case, the first line contains two integer N and M, where N (1 <= N <= 10^5) is the number of flowers, and M (1 <= M <= 10^5) is the query times. 
In the next N lines, each line contains two integer S i
 and T i (1 <= S i <= T i <= 10^9), means i-th flower will be blooming at time [S i, T i].
In the next M lines, each line contains an integer T i, means the time of i-th query.  

 

Output For each case, output the case number as shown and then print M lines. Each line contains an integer, meaning the number of blooming flowers.
Sample outputs are available for more details.  

 

Sample Input 2 1 1 5 10 4 2 3 1 4 4 8 1 4 6     Sample Output Case #1: 0 Case #2: 1 2 1   題意: 有n朵花,每一朵花只會在固定的時間範圍內綻放,m次詢問,讓你求在某個時刻有多少朵花是綻放的。 思路: 這題可以看成是樹狀陣列的區間更新,給出每一朵花開放的時間範圍,就相當於做一次區間更新,這個範圍內的每個點加1,直接使用樹狀陣列區間跟新的模板就好了。 可是這題有個問題,那就是花開放範圍的資料極大(1-10^9),無法直接開陣列儲存每一個點。那怎麼辦呢,很明顯需要用到資料的離散化。 我們可以發現,雖然花開放範圍極大,但是總共只有n朵花,n最大是10^5,每一個範圍由兩個數l,r組成,再加上最多10^5個查詢數,也就意味著一組資料最多出現3*(10^5)個不同的資料,陣列完全能夠存下。而且我們判斷花是否在某一時刻開放,只需要知道數與數之間的相對大小,而不需要在意具體數值(某一時刻在 l , r之間,即花是開的),所以,這就滿足了離散化的條件。 我們對每一朵花開放的範圍進行離散化,也對查詢的時刻進行離散化,這樣,就不會改變他們的相對大小。然後使用樹狀陣列區間更新+單點查詢即可。 離散化的方法:將所有出現的數存入陣列,去除重複出現的數,再進行排序,排序後這個數在陣列中對應的下標,即為其離散化之後的數值。   程式碼:
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<string>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<stack>
 8 #include<climits>
 9 #include<map>
10 #include<queue>
11 #define eps 1e-7
12 #define ll long long
13 #define inf 0x3f3f3f3f
14 #define pi 3.141592653589793238462643383279
15 using namespace std;
16 const int MAXN = 3e5 + 21;
17 
18 int getNum[MAXN],li[MAXN/3],ri[MAXN/3],c[MAXN];
19 
20 int lowBit(int x)
21 {
22     return x&(-x);
23 }
24 
25 void add(int x,int num,int len) //區間更新 
26 {
27     for(int i=x; i<=len; i+=lowBit(i))
28     {
29         c[i] += num;
30     }
31 }
32 
33 ll query(int x) //單點查詢 
34 {
35     ll ans = 0;
36     for(int i=x; i>0; i-=lowBit(i))
37     {
38         ans += c[i];
39     }
40     return ans;
41 }
42 
43 int bSerach(int num,int len) //找出某個數在陣列中的下標,並返回下標+1 
44 {
45     return lower_bound(getNum,getNum+len,num) - getNum + 1;
46 }
47 
48 int main()
49 {
50     int t,n,m,cnt = 0;
51     cin>>t;
52     while(t--)
53     {
54         memset(c,0,sizeof(c));
55         memset(getNum,0,sizeof(getNum));
56     
57         scanf("%d%d",&n,&m);
58         
59         int cnt1 = 0;
60         
61         for(int i=0; i<n; ++i)
62         {
63             scanf("%d%d",&li[i],&ri[i]);
64             getNum[cnt1++] = li[i]; //將花開放範圍出現的資料存入陣列 
65             getNum[cnt1++] = ri[i];
66         }
67         
68         int ques[MAXN/3];
69         for(int i=0; i<m; ++i)
70         {
71             scanf("%d",&ques[i]); 
72             getNum[cnt1++] = ques[i]; //將查詢出現的資料存入陣列 
73         }
74         
75         sort(getNum,getNum+cnt1); //給所有出現的數排序 
76         
77         int cnt2 = 1;
78         for(int i=1; i<cnt1; ++i)
79         {
80             if(getNum[i] != getNum[i-1]) //去除重複的數 
81                 getNum[cnt2++] = getNum[i];
82         }
83         
84         
85         for(int i=0; i<n; ++i) //樹狀陣列區間更新
86         {
87             add( bSerach(li[i],cnt2), 1,cnt2);
88             add( bSerach(ri[i],cnt2)+1, -1,cnt2);
89         }
90         
91         printf("Case #%d:\n",++cnt);
92         for(int i=0; i<m; ++i)
93         {
94             cout<<query( bSerach(ques[i], cnt2) )<<endl; //樹狀陣列單點查詢 
95         }
96     }
97     return 0;
98 }