洛谷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\n",double(clock())/1000.0);
 29 #define TO(j) printf(#j": %d\n",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\n", 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 }
时间: 2024-08-03 19:25:42

洛谷P1848 [USACO12OPEN]书架Bookshelf的相关文章

洛谷——P2676 超级书架

https://www.luogu.org/problem/show?pid=2676#sub 题目描述 Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了.现在,只有书架的顶上还留有一点空间. 所有N(1 <= N <= 20,000)头奶牛都有一个确定的身高H_i(1 <= H_i <= 10,000).设所有奶牛身高的和为S.书架的高度为B,并且保证 1 <= B <= S < 2,000

洛谷P2676 超级书架

题目描述 Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了.现在,只有书架的顶上还留有一点空间. 所有N(1 <= N <= 20,000)头奶牛都有一个确定的身高H_i(1 <= H_i <= 10,000).设所有奶牛身高的和为S.书架的高度为B,并且保证 1 <= B <= S < 2,000,000,007. 为了够到比最高的那头奶牛还要高的书架顶,奶牛们不得不象演杂技一般,一头站在另

洛谷P2677 超级书架 2

题目描述 Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了.现在,只有书架的顶上还留有一点空间. 所有N(1 <= N <= 20)头奶牛都有一个确定的身高H_i(1 <= Hi <= 1,000,000 - 好高的奶牛><). 设所有奶牛身高的和为S.书架的 高度为B,并且保证1 <= B <= S. 为了够到比最高的那头奶牛还要高的书架顶,奶牛们不得不象演杂技一般,一头站在另一头的背

洛谷 P2677 超级书架 2

P2677 超级书架 2 题目描述 Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了.现在,只有书架的顶上还留有一点空间. 所有N(1 <= N <= 20)头奶牛都有一个确定的身高H_i(1 <= H_i <= 1,000,000 - 好高的奶牛>_<).设所有奶牛身高的和为S.书架的 高度为B,并且保证1 <= B <= S. 为了够到比最高的那头奶牛还要高的书架顶,奶牛们不得不象演

洛谷P2596 [ZJOI2006]书架【splay】

题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置.不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1.X或X+1本书. 当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友

洛谷P2676 超级书架 题解

题目传送门 题目一看就是贪心.C++福利来了:sort. 基本思路就是:要使奶牛最少那么肯定高的奶牛先啦. 直接排序一遍(从高到矮)然后while,搞定! #include<bits/stdc++.h> #define ll long long using namespace std; ll N,B,H[20010]; bool cmp(int x,int y){return x>y;} int main(){ scanf("%lld%lld",&N,&

洛谷1103 书本整理

洛谷1103 书本整理 本题地址:http://www.luogu.org/problem/show?pid=1103 题目描述 Frank是一个非常喜爱整洁的人.他有一大堆书和一个书架,想要把书放在书架上.书架可以放下所有的书,所以Frank首先将书按高度顺序排列在书架 上.但是Frank发现,由于很多书的宽度不同,所以书看起来还是非常不整齐.于是他决定从中拿掉k本书,使得书架可以看起来整齐一点. 书架的不整齐度是这样定义的:每两本书宽度的差的绝对值的和.例如有4本书: 1x2 5x3 2x4

洛谷 P1103 书本整理(动规)

洛谷 P1103 书本整理 题目描述 Frank是一个非常喜爱整洁的人.他有一大堆书和一个书架,想要把书放在书架上.书架可以放下所有的书,所以Frank首先将书按高度顺序排列在书架上.但是Frank发现,由于很多书的宽度不同,所以书看起来还是非常不整齐.于是他决定从中拿掉k本书,使得书架可以看起来整齐一点. 书架的不整齐度是这样定义的:每两本书宽度的差的绝对值的和.例如有4本书: 1x2 5x3 2x4 3x1 那么Frank将其排列整齐后是: 1x2 2x4 3x1 5x3 不整齐度就是2+3

洛谷 P2709 BZOJ 3781 小B的询问

题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. 输入输出格式 输入格式: 第一行,三个整数N.M.K. 第二行,N个整数,表示小B的序列. 接下来的M行,每行两个整数L.R. 输出格式: M行,每行一个整数,其中第i行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3