hdu2795(線段樹單點更新&區間最值)
阿新 • • 發佈:2017-06-11
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> 3View Code#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 }
其實這個代碼中的更新的路徑和查詢的路徑是一樣的,可以優化一下,將更新寫進查詢裏面去;
優化代碼:
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(線段樹單點更新&區間最值)