hdu2795(线段树单点更新&区间最值)
题目链接: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 }
其实这个代码中的更新的路径和查询的路径是一样的,可以优化一下,将更新写进查询里面去;
优化代码:
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 }
我就是我,颜色不一样的烟火 --- geloutingyu