zoukankan      html  css  js  c++  java
  • hdu2795-Billboard(线段树应用好题)

    题意:有一块高*宽为h*w的牌子,n次操作输入一个val,每次操作贴一个1*val的牌子,贴法要求采用贪心策略:1.尽可能往上。2.在1的前提下尽可能往左。如果当前牌子不能贴上去就输出-1,否则输出当前牌子贴的位置的高度。

    分析:线段树维护一下区间最大值,初始全部为设为w。考虑-1的情况,如果整个区间的最大值都不能满足val,那么说明任何一个地方都不能把这块牌子放上去,即输出-1,否则必然有至少一个点能把这块牌子放上。如何满足贪心策略1?线段树叶子结点为单点,其余为区间,自顶向下二分到单点就是答案,如果当前节点左下的值比val大,那么说明答案在左边,否则在右边。至于贪心策略2只需要每次更新最大值减去当前的val即可。

    const int N = 2e5+10;
    int maxx[N<<2], h, w, n;
    
    void upd(int l, int r, int p, int i, int val) {
      if (l == r) {maxx[i] = val;return;}
      int mid = l + r >> 1;
      if (p <= mid) upd(l,mid,p,ls,val);
      else upd(mid+1,r,p,rs,val);
      maxx[i] = max(maxx[ls], maxx[rs]);
    }
    
    void run() {
      while (~scanf("%lld%lld%lld",&h,&w,&n)) {
        int e = min(h, n);
        for (int i = 1; i <= e; i++) upd(1,e,i,1,w);
        for (int i = 1, tmp; i <= n; i++) {
          tmp = rd();
          if (tmp > maxx[1]) puts("-1");
          else {
            int i = 1, l = 1, r = e;
            while (l < r) {
              int mid = l + r >> 1;
              if (maxx[ls] >= tmp) i = (ls), r = mid;
              else i = (rs), l = mid+1;
            }
            printf("%lld
    ",l);
            upd(1,e,l,1,maxx[i]-tmp);
          }
        }    
      }
    }
  • 相关阅读:
    发一注册表监控驱动代码
    Nikto
    在c#使用IOCP(完成端口)的简单示例
    C#中ref和out的使用小结
    Powerful x86/x64 Mini HookEngine
    C语言写的多线程下载器
    快速排序算法c#
    拓扑排序
    Dijkstra算法
    SRM 550 DIV2
  • 原文地址:https://www.cnblogs.com/hznudreamer/p/13648788.html
Copyright © 2011-2022 走看看