• 洛谷P1848 [USACO12OPEN]书架Bookshelf


    当农夫约翰闲的没事干的时候,他喜欢坐下来看书。多年过去,他已经收集了 N 本书 (1 <= N <= 100,000), 他想造一个新的书架来装所有书。

    每本书 i 都有宽度 W(i) 和高度 H(i)。书需要按顺序添加到一组书架上;比如说,第一层架子应该包含书籍1 ... k,第二层架子应该以第k + 1本书开始,以下如此。每层架子的总宽度最大为L(1≤L≤1,000,000,000)。每层的高度等于该层上最高的书的高度,并且整个书架的高度是所有层的高度的总和,因为它们都垂直堆叠。

    请帮助农夫约翰计算整个书架的最小可能高度。

    有N(1 <= N <= 100000)本书,每本书有一个宽度W(i),高度H(i),(1 <= H(i) <= 1,000,000; 1 <= W(i) <= L)。

    现在有足够多的书架,书架宽度最多是L (1 <= L <= 1,000,000,000),把书按顺序(先放1,再放2.....)放入书架。某个书架的高度是该书架中所放的最高的书的高度。

    将所有书放入书架后,求所有书架的高度和的最小值?

    题目大意:一段元素,每个元素有两个权值h和w,要把它分成若干段(不限制段数),每一段的 $sum{w}$ 不能超过 L,最终的代价是每段的最大元素之和 $ sum{max_{h}} $ ,最小化代价

    终于过了这个破题
    第一次WA因为没判边界条件
    第二次WA因为答案爆了int
    第三次T了?没关系,进大牛开O2稳过
    题解:f[i] 分完i这个数然后pia叽断开的最小高度和
    f[i] = min{f[j]+max{h[j+1]..h[i]}} (sum[i]-sum[j]<=L)
    我们发现对于一个固定的i,max{h[j+1]..h[i]}随j增大单调不增,f[j]随j增大单调不减
    而且对于某一些区间,它们中的 max{h[j+1]..h[i]}是一样的,那么这段区间中的最优决策一定是把这一段区间要么全分到后面,要么全分到前面(暂时不考虑长度太长的情况)
    那我们可以对所有的区间维护一下以它们的左边界-1位决策点的答案,最终的最优解一定在这些答案之中
    然后考虑后面新增了一个数h[i],如果h[i]>h[j-1],那么j-1所在的那一段区间就没用了(它的最大h被迫上升了),把这一段区间和i这个位置合并,重复向前找区间,直到最大值比h[i]大位置,这是一个典型的单调队列从队尾踢元素的操作
    然后考虑从队首踢元素,显然如果一个区间太靠左了,那么这个区间可能会因为sum[i]-sum[j]太大而无法取到
    然后按照这个思路从队首删除元素就好了,有的时候是把一整个区间都删掉,有的时候是右移一个区间的左端点,注释应该写得挺清楚了
    然后我们怎么维护答案呢?网上有的题解说用一颗平衡树实现,其实没那么烦,因为我们只要支持插入,删除,取最小值,维护一个双堆就行了
    然而pq真是慢啊,要是不开O2会T两个点,开了O2是洛谷第2(毕竟堆比平衡树常数小多了),第1是个骗了数据的baka

      1 #include <iostream>
      2 #include <cstdlib>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <string>
      6 #include <cstring>
      7 #include <cmath>
      8 #include <map>
      9 #include <stack>
     10 #include <set>
     11 #include <vector>
     12 #include <queue>
     13 #include <time.h>
     14 #define eps 1e-7
     15 #define INF 0x3f3f3f3f
     16 #define MOD 1000000007
     17 #define rep0(j,n) for(int j=0;j<n;++j)
     18 #define rep1(j,n) for(int j=1;j<=n;++j)
     19 #define pb push_back
     20 #define set0(n) memset(n,0,sizeof(n))
     21 #define ll long long
     22 #define ull unsigned long long
     23 #define iter(i,v) for(edge *i=head[v];i;i=i->nxt)
     24 #define mp make_pair
     25 #define max(a,b) (a>b?a:b)
     26 #define min(a,b) (a<b?a:b)
     27 #include<functional>
     28 #define print_rumtime printf("Running time:%.3lfs
    ",double(clock())/1000.0);
     29 #define TO(j) printf(#j": %d
    ",j);
     30 //#define OJ
     31 using namespace std;
     32 const int MAXINT = 100010;
     33 const int MAXNODE = 100010;
     34 const int MAXEDGE = 2 * MAXNODE;
     35 char BUF, *buf;
     36 int read() {
     37     char c = getchar(); int f = 1, x = 0;
     38     while (!isdigit(c)) { if (c == '-') f = -1; c = getchar(); }
     39     while (isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
     40     return f*x;
     41 }
     42 char get_ch() {
     43     char c = getchar();
     44     while (!isalpha(c)) c = getchar();
     45     return c;
     46 }
     47 //------------------- Head Files ----------------------//
     48 pair<int, int> q[MAXINT];
     49 struct pq {
     50     priority_queue<ll,vector<ll>,greater<ll> > q, d;
     51     void del(ll p) {
     52         d.push(p);
     53     }
     54     void push(ll p) {
     55         q.push(p);
     56     }
     57     ll top() {
     58         while (!d.empty() && d.top() == q.top()) q.pop(), d.pop();
     59         return q.top();
     60     }
     61     void pop() {
     62         while (!d.empty() && d.top() == q.top()) q.pop(), d.pop();
     63         q.pop();
     64     }
     65 }ans;
     66 ll f[MAXINT], l,n;
     67 int w[MAXINT], H[MAXINT];
     68 ll sum[MAXINT];
     69 void get_input();
     70 void work();
     71 int main() {
     72     get_input();
     73     work();
     74     return 0;
     75 }
     76 void work() {
     77     pair<int, int> *h, *t;
     78     h = t = q;
     79     *t++ = mp(0, INF);//哨兵元素!
     80     rep1(i, n) {
     81         int p = i;
     82         while ((t - 1)->second<H[i]) {
     83             ans.del((t - 1)->second + f[(t - 1)->first - 1]);
     84             p = (t - 1)->first;
     85             t--;
     86         }
     87         *t++ = mp(p, H[i]);
     88         ans.push(f[p - 1] + H[i]);
     89         h++;
     90         while ( (h + 1<t) && sum[i] - sum[(h + 1)->first - 1]>l) ans.del(h->second + f[h->first - 1]), h++; //delete the whole segment
     91         ans.del(h->second + f[h->first - 1]);
     92         for (; sum[i] - sum[h->first-1]>l; h->first++);//delete some element
     93         if ((h+1<t)&&h->first == (h + 1)->first) h++;
     94         else ans.push(h->second + f[h->first - 1]);
     95         h--;
     96         *h = mp(0, INF);
     97         f[i] = ans.top();
     98     }
     99     printf("%lld
    ", f[n]);
    100 }
    101 void get_input() {
    102     n = read(); l = read();
    103     rep1(i, n) H[i] = read(), w[i] = read(), sum[i] = sum[i - 1] + w[i];
    104 }
    许愿弥生改二
  • 相关阅读:
    在ubuntu 12.04 x64下编译hadoop2.4
    Learn ZYNQ (9)
    Learn ZYNQ (8)
    Jquery 中 ajaxSubmit使用讲解(转)
    JSON.parse()和JSON.stringify()的区别
    $('div','li'),$('div , li'),$('div li')的区别
    用正则表达式来去除字符的前后空格
    git add 命令添加所有改动内容
    js基础知识
    Web开发学习笔记
  • 原文地址:https://www.cnblogs.com/LoveYayoi/p/6764738.html
Copyright © 2020-2023  润新知