jzoj2931 书架
来源:互联网 发布:亚马逊的大数据行动 编辑:程序博客网 时间:2024/05/03 16:57
Description
当Farmer John闲下来的时候,他喜欢坐下来读一本好书。
多年来,他已经收集了N本书 (1 <= N <= 100,000)。
他想要建立一个多层书架,来存放它们。
每本书 i 拥有一个宽度 W(i)和一个高度 H(i)。
所有的书需要按顺序,放到书架的每一层。
举例来说,第一层书架放k本书,应该放书1…k;第二层书架从第k+1本书开始放……。
每层书架的宽度最多为L (1 <= L <= 1,000,000,000)。
每层书架的高度为该层最高的那本书的高度。
书架的总高度为每层书架高度之和。
请帮FJ计算书架可能的最小总高度。
简洁题意
给定相同长度序列a,b,要求划分段满足每一段的
解法
最大值最小化这种神奇的问题,一般可以考虑两种方法
1.二分,转化为判定问题
2.DP只要是有max min这种东西 我们可以考察其单调性或可维护性,并加以数据结构维护最值s
这里由于是序列划分,所以我们选择第二种
设
然后我们就得到了一个n^2的简单DP做法
其中maxh_j+1表示j+1~i的最大h
可以发现f与maxh的单调性(显然)
再设ok为当前i到ok内(包括)的宽度可以满足
那这个时候我们的问题就是如何在ok-1~i-1这个区间内取j使得f[i]尽量小
我们选择种一颗线段树,维护区间中最小的maxh+f[最左点] 因为我们知道f满足单调不递减
每一次取答案,其实就是query(ok-1~i-1)
那如何维护呢
已知maxh的单调性,那么我们去找,k=
这个可以考虑二分和单调队列
找到这个k之后,我们就要区间修改线段树[k,i-1]的值
因为f[最左点]这个值是给定的不需要维护,所以我们就打一个lazy标记表示该区间所有点的maxh都替换为更新成的那个. 这样查询的时候顺手清理掉lazy标记就可以n log n过掉这一题了
恶心的地方
由于c++不报数组上溢
所以莫名其妙的单调队列被改
所以莫名奇妙的调了一天
所以还是机智的发现了
我真聪明(真不要脸)
CODE
#include <cstdio>#include <iostream>#include <cstring>#define MAXN 100100#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)#define DEBUG falseusing namespace std;long long minHW,l,n,w[MAXN*5],h[MAXN*5],f[MAXN*5],pre[MAXN*5],t[MAXN*4*5],lazy[MAXN*4*5],ok,result,q[MAXN*5],perLoc[MAXN*5],head,tail;long min(long a,long b) { return (a>b)?b:a;}void clearLazy(int x,int l,int r) { //cout<<x<<" "<<leftLoc<<" "<<lazy[x]<<endl; if (lazy[x]==0) return; t[x]=f[l]+lazy[x]; t[x*2]=f[l]+lazy[x]; t[x*2+1]=f[x*2]+lazy[x]; lazy[x*2]=lazy[x*2+1]=lazy[x]; lazy[x]=0;}void update(int x) { t[x]=min(t[x*2+1],t[x*2]);}int push(long long x,int itsLoc) { while (tail>0 && q[tail]<x) { perLoc[tail]=0; tail--; } q[++tail]=x; perLoc[tail]=itsLoc; //if (tail<head) return perLoc[tail]; else return perLoc[tail-1];}void headAdd() { while (perLoc[head]<ok && head<=tail) head++;}void query(int x,int l,int r,int fl,int fr) { if (l>fr || r<fl) return; if (DEBUG) cout<<l<<" "<<r<<" "<<fl<<" "<<fr<<endl; if (l>=fl && r<=fr) { clearLazy(x,l,r); result=(result<t[x])?result:t[x]; return; } clearLazy(x,l,r); query(x*2,l,(l+r)>>1,fl,fr); query(x*2+1,((l+r)>>1)+1,r,fl,fr);}void change(int x,int l,int r,int fl,int fr,long long v) { if (l>fr || r<fl) return; if (DEBUG) cout<<l<<" "<<r<<" "<<fl<<" "<<fr<<endl; if (fl<=l && r<=fr ) { if (DEBUG) cout<<lazy[x]<<"=>"<<v<<endl; lazy[x]=v; t[x]=f[l]+v; //clearLazy(x,l,r); return; } clearLazy(x,l,r); change(x*2, l,(l+r)>>1,fl,fr,v); change(x*2+1,((l+r)>>1)+1,r,fl,fr,v); update(x);}int main() { cin>>n>>l; fo(i,1,n) { scanf("%lld %lld",&h[i],&w[i]); pre[i]=pre[i-1]+w[i]; } //memset(f,127,sizeof f); f[0]=0; ok=1; head=1; tail=0; perLoc[0]=-1; fo(i,1,n) { //if (i>=3) cout<<pre[i]<<endl; perLoc[0]=-1; while (pre[i]-pre[ok-1]>l) ok++; int loc = push(h[i],i); //if (i>=3) cout<<loc+1<<endl; if (DEBUG) cout<<"change"<<endl; change(1,0,n,loc,i-1,h[i]); result=99999999999999999; if (DEBUG) cout<<"query"<<endl; query(1,0,n,ok-1,i-1); if (result==99999999999999999) result=0; f[i]=result; //change(1,0,n,i,i); if (DEBUG) cout<<f[i]<<endl; } cout<<f[n]<<endl; return 0;}
- jzoj2931 书架
- 书架
- 书架
- 书架
- 书架
- 沙发?书架?书架沙发。
- 大学书架
- 大学书架
- 程序员书架
- 书架评论
- 嵌入式书架
- 虚拟书架
- linux书架
- Linux书架
- 程序员------- 书架
- Linux书架
- Linux书架
- Linux书架
- BigInteger类(大数运算)
- android中Intent的使用
- Win10的UWP之标题栏的返回键(一)
- HDU 1598 find the most comfortable road
- 【Jenkins】包含dubbo服务的war包自动部署tomcat
- jzoj2931 书架
- android中判断关于文本展示是否出现省略号的判断
- Qt之QSequentialAnimationGroup
- mysql添加外键
- There was an internal API error.
- 生命周期方法
- Hbase分布式集群安装配置
- Android自定义控件:动画类----alpha、scale、translate、rotate、set的xml属性及用法
- 准备食物