梦工厂 (yume.cpp/c/pas)
Time Limit: 1 s Memory Limit: 128 M
问题描述
「有时候用烂了的名字也会别有深意」
——摘自EN 语录
“这里是制造快乐,编织幸福的梦工厂!才不是你们想的什么奇怪的工厂呢!哼!”
这是你来到这个奇妙的地方所听到的第一句话,竟然还是一头身长三米的狗熊发出来的。
一开始看到梦工厂这块牌匾时,你心里想的是什么呢?如果真的是洋溢着青涩而纯洁的
梦想,那就太棒了!
初来乍到,狗熊先生决定给你先大致地讲解一下工厂的运作过程。
“要知道,我们这里可是梦工厂,为小孩子们生产快乐与幸福的梦工厂!”,狗熊先生
不断地重复着梦工厂的定义。尽管脑袋晕晕乎乎的,但是你最终还是知道了,这个工厂是专
门生产快乐与幸福这样的情绪的,用来送给那些闷闷不乐或者是受到了挫折的小孩子,让他
们重展笑颜。
“但是,我们遇到了一个问题…”,狗熊先生的语气低沉了下来。
“最近不开心的小孩子越来越多了,我们需要生产的快乐也越来越多了,但是我们的生
产线是由n道工序构成,每个单位时间里每道工序最多只能容纳一个快乐。当一个快乐被
一个工序加工完后,会立刻传到下一道工序。”
“然后呢,怎么了,这不挺好的吗?”,你好奇道。
“好什么呀!快乐会被强制传到下一道工序,如果下一道工序里也有一个快乐的话,那
就会爆炸!爆炸懂吗!瞬间爆炸!”,狗熊先生语气高昂了起来。
“之前我们为了防止爆炸,都是等一个快乐所有工序生产好之后才开始生产另一个快乐
的。但是我想了几百年,觉得可以早点开始生产的,只要保证它们不会在同一时刻出现在同
一道工序上就行了。”,狗熊先生骄傲地挺起胸膛,有点可怕。
“顺便告诉你吧!每道工序有个复杂指数Ti,一个快乐有个快乐指数Fj,第j个快乐在
第i道工序中要消耗的时间是Fj?Ti,而且快乐必须按顺序生产。”
“既然我什么都告诉你了,嘿嘿”,狗熊先生露出了狰狞的笑容,食肉的
“你就帮我安排一下怎么生产最好吧,告诉我最短的全部生产完的时间就
哦,不然就拿你打牙祭!”
这是梦工厂吗?是梦吧?
输入格式
第一行两个整数n和m表示工序道数、需生产的快乐个数。
第二行n个整数,分别表示复杂指数Ti。
第三行m个整数,分别表示快乐指数Fi。
输出格式
一个正整数为最短时间。
Sample Input
3 3
2
1
1
2
1
1
Sample Output
11
题解与吐槽
南雅的这题面。。。说人话好不
花了快2个小时写这题暴力,又两个小时调一个傻逼凸包。
感觉终于有点明白斜率优化是啥东西了。
我们先把Ti的前缀和求出来,记做sumi,然后维护把前i?1个物品全部处理完的时间。然后对于第i件物品,我们要使它无论如何不能与前一个同时出现在一个阶段,所以我们可以求出sumj?fi?1?sumj?1?fi的最大值,并以这个值减去节省下来的时间。
上面那个是暴力,然后我们发现可以把那个式子转化一下,就变成了经典的斜率优化问题。我们维护(sumi?1,sumi)形成的上凸包,然后每次询问时二分查找即可。
下面上代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int inf=0x3f3f3f3f;
int getint()
{
char c=getchar();
int f=1,g=0;
while(c>‘9‘ || c<‘0‘){if(c==‘-‘)f=-1;c=getchar();}
while(c<=‘9‘ && c>=‘0‘)g=(g<<3)+(g<<1)+c-‘0‘,c=getchar();
return f*g;
}
const int maxn=2000005;
int top;
int sum[maxn];
int f[maxn];
int t[maxn];
int n,m;
db slp[maxn];
ll ans;
int q[maxn];
db slope(int j,int k)
{
db temp1=(db)sum[j-1]-(db)sum[k-1];
db temp2=(db)sum[j]-(db)sum[k];
return temp1/temp2;
}
int findpos(db x)
{
int l=1;
int r=top-1;
if(x<slp[l])return q[1];
if(x>slp[r])return q[top];
while(l<r)
{
int mid=(l+r)>>1;
if(slp[mid]<x)
{
l=mid+1;
}
else r=mid;
}
return q[l];
}
int main()
{
freopen("yume.in","r",stdin);
freopen("yume.out","w",stdout);
n=getint();
m=getint();
for(int i=1;i<=n;i++)
{
t[i]=getint();
sum[i]=sum[i-1]+t[i];
}
for(int i=1;i<=m;i++)
{
f[i]=getint();
}
for(int i=1;i<=n;i++)
{
while(top>1 && slp[top-1]>=slope(q[top],i))
{
top--;
}
q[++top]=i;
slp[top-1]=slope(q[top],q[top-1]);
}
for(int i=1;i<=m;i++)
{
db tem=(db)f[i-1]/(db)f[i];
int temp=findpos(tem);
ll mx=(ll)sum[temp]*(ll)f[i-1]-(ll)sum[temp-1]*(ll)f[i];
mx-=(ll)sum[n]*((ll)f[i-1]-(ll)f[i]);
mx=max(0ll,mx);
ans+=mx;
}
printf("%lld\n",ans);
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。