[关闭]
@Acqua 2018-12-20T12:09:43.000000Z 字数 894 阅读 1051

HDU2795 Billboard(Dec. 20th, 2018)

线段树

题目来源

题意:有一个长为,宽为的公告板,现在要往上面贴条长度为,宽度为1的公告,每个公告必须横着贴,且必须贴在尽量靠左上的位置。求每个公告所贴的行号,若无法贴上,输出-1。

思路:统计每行剩余空间,线段树维护区间最大值,与模板相比略有变形

代码:

  1. // La Lune
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. using namespace std;
  7. const int N = 2e5 + 5;
  8. int t[N << 2];
  9. int h, w, n, Ir;
  10. void pushup(int u){
  11. t[u] = max(t[u << 1], t[u << 1 | 1]);
  12. }
  13. void build(int u, int l, int r){
  14. if(l == r){
  15. t[u] = w;
  16. return;
  17. }
  18. int mid = l + r >> 1;
  19. build(u << 1, l, mid); build(u << 1 | 1, mid + 1, r);
  20. pushup(u);
  21. }
  22. void query(int u, int l, int r, int len){
  23. if(l == r){
  24. if(t[u] >= len){
  25. t[u] -= len;
  26. printf("%d\n", l);
  27. Ir = 1;
  28. }
  29. return;
  30. }
  31. int mid = l + r >> 1;
  32. if(t[u << 1] >= len) query(u << 1, l, mid, len);
  33. else if(t[u << 1 | 1] >= len) query(u << 1 | 1, mid + 1, r, len);
  34. pushup(u);
  35. }
  36. int main(){
  37. while(~scanf("%d %d %d", &h, &w, &n)){
  38. if(h > n) h = n;
  39. build(1, 1, h);
  40. for(int i = 1; i <= n; i++){
  41. Ir = 0;
  42. int len; scanf("%d", &len);
  43. // printf("ans = ");
  44. query(1, 1, h, len);
  45. if(!Ir) printf("-1\n");
  46. }
  47. }
  48. return 0;
  49. }

反思:
1. 代码很裸,但是需要学习这种转化方式。
2. 做过的题要时常复习,不要把写题解形式化。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注