1. 程式人生 > >hdu2795(線段樹單點更新&區間最值)

hdu2795(線段樹單點更新&區間最值)

ref 當前 廣告 sed gif .cn lap ostream spa

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2795

題意:有一個 h * w 的板子,要在上面貼 n 條 1 * x 的廣告,在貼第 i 條廣告時要盡量將其靠上貼,並輸出其最上能貼在哪個位置;

思路:可以將每行剩余空間大小存儲到一個數組中,那麽對於當前 1 * x 的廣告,只需找到所有剩余空間大於的 x 的行中位置最小的即可;

不過本題數據量為 2e5,直接暴力因該會 tle.可以用個線段樹維護一下區間最大值,然後查詢時對線段樹二分即可;

代碼:

技術分享
 1 #include <iostream>
 2 #include <stdio.h>
 3
#define lson l, mid, rt << 1 4 #define rson mid + 1, r, rt << 1 | 1 5 using namespace std; 6 7 const int MAXN = 2e5 + 10; 8 int Max[MAXN << 2], h, w, n; 9 10 int max(int a, int b){ 11 return a > b ? a : b; 12 } 13 14 void push_up(int rt){ 15 Max[rt] = max(Max[rt << 1
], Max[rt << 1 | 1]); 16 } 17 18 void build(int l, int r, int rt){//建樹 19 Max[rt] = w; 20 if(l == r) return; 21 int mid = (l + r) >> 1; 22 build(lson); 23 build(rson); 24 } 25 26 void update(int p, int x, int l, int r, int rt){//單點更新 27 if(l == r){ 28 Max[rt] -= x;
29 return; 30 } 31 int mid = (l + r) >> 1; 32 if(p <= mid) update(p, x, lson); 33 else update(p, x, rson); 34 push_up(rt); 35 } 36 37 int query(int x, int l, int r, int rt){//查詢 38 if(l == r) return l; 39 int mid = (l + r) >> 1; 40 int ans = 0; 41 if(Max[rt << 1] >= x) ans = query(x, lson); 42 else ans = query(x, rson); 43 return ans; 44 } 45 46 int main(void){ 47 while(~scanf("%d%d%d", &h, &w, &n)){ 48 if(h > n) h = n; 49 build(1, h, 1); 50 while(n--){ 51 int x, cnt; 52 scanf("%d", &x); 53 if(Max[1] < x){ 54 printf("-1\n"); 55 continue; 56 }else printf("%d\n", cnt = query(x, 1, h, 1)); 57 update(cnt, x, 1, h, 1); 58 } 59 } 60 return 0; 61 }
View Code

其實這個代碼中的更新的路徑和查詢的路徑是一樣的,可以優化一下,將更新寫進查詢裏面去;

優化代碼:

技術分享
 1 #include <iostream>
 2 #include <stdio.h>
 3 #define lson l, mid, rt << 1
 4 #define rson mid + 1, r, rt << 1 | 1
 5 using namespace std;
 6 
 7 const int MAXN = 2e5 + 10;
 8 int Max[MAXN << 2], h, w, n;
 9 
10 int push_up(int rt){
11     Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]);
12 }
13 
14 void build(int l, int r, int rt){
15     Max[rt] = w;
16     if(l == r) return;
17     int mid = (l + r) >> 1;
18     build(lson);
19     build(rson);
20 }
21 
22 int query(int x, int l, int r, int rt){
23     if(l == r){
24         Max[rt] -= x;
25         return l;
26     }
27     int mid = (l + r) >> 1;
28     int cnt = (Max[rt << 1] >= x) ? query(x, lson) : query(x, rson);
29     push_up(rt);
30     return cnt;
31 }
32 
33 int main(void){
34     while(~scanf("%d%d%d", &h, &w, &n)){
35         if(h > n) h = n;
36         build(1, h, 1);
37         while(n--){
38             int x;
39             scanf("%d", &x);
40             if(Max[1] < x) printf("-1\n");
41             else printf("%d\n", query(x, 1, h, 1));
42         }
43     }
44     return 0;
45 }
View Code

hdu2795(線段樹單點更新&區間最值)