https://nanti.jisuanke.com/t/41306
题意:n个人分别在ti时间来到洗衣房洗衣服,每个人可以选择洗衣机洗和手洗,手洗花费y时间,机洗花费x时间,只有一台洗衣机,所以多个人想用要排队。现在要求对于每一个在[1,y]范围内的x,输出所有人洗完衣服所需要的最小时间。
如果有错误欢迎指正,这道题第一种做法是看到这个博客才知道的:
https://blog.csdn.net/TDD_Master/article/details/100374149#commentsedit
但是始终不明白为什么不需要考虑n-p这个点的情况,所以我的代码还是考虑了,也是A了哒。
对于p的分析是我自己的理解,可能会有错误(目前自我感觉还挺对咳咳
如果有错误,欢迎指正!!!
分析:
假设
首先,机洗时间一定<=手洗时间,所以最后一个人肯定可以是机洗啦。另外如果第i个人选择手洗,则他前面的人没有选择机洗的必要,因为这个人手洗肯定贼慢,还是由这个人影响最后的答案。所以可以知道,假设从第x个人开始选择机洗比较快,那后面的人都是机洗,前面的人可以假装都是手洗。
假设从第i个人开始机洗,i个人机洗的时间就是max{ tj+(n-j+1)*x } (i<=j<=n)
答案是 (1<=i<=n,i<=j<=n)
就是下面绿绿的那条的最低点。注意最低点的横坐标不一定是整数咳咳。
假设最后p个人选择机洗的时候,手洗时间恰好开始>=机洗时间([i,n]机洗)
则此时,
又因为 ,所以 (因为
意思就是确定x的情况下,最多最多y/x个人用洗衣机
那么从n往前for到i-1(就是点n-p),维护max{ tj+(n-j+1)*x },咳反正就是可以暴力求答案了啦
分析一下复杂度,就是
差不多是ylogy叭
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1e6+6;
const ll INF=8e18;
ll n,y,a[maxn];
ll ans[maxn];
int main(){
while(~scanf("%lld%lld",&n,&y)){
for(ll i=1;i<=n;i++) scanf("%lld",&a[i]);
sort(a+1,a+n+1);
a[0]=-y;
ll low=n,g;
for(ll x=y;x>=1;x--){
int p=y/x;
ll maxx=a[n]+x,res=max(a[n-1]+y,maxx);
for(int j=n-1;j>=n-p&&j;j--){
maxx=max(maxx,a[j]+(n-j+1)*x);
res=min(res,max(a[j-1]+y,maxx));
}
ans[x]=res;
}
for(ll i=1;i<=y;i++) printf("%lld%c",ans[i],i==y?'\n':' ');
}
return 0;
}
李超树的话就和题解上说的差不多啦
有学弟是用下凸包写的后面部分emmm并不知道具体是怎么实现的
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1e6+6;
const ll INF=8e18;
ll n,y,a[maxn];
double Intersection(double k1,double b1,double k2,double b2){return 1.0*(b2-b1)/(k1-k2);}
ll segb[maxn<<2],segk[maxn<<2];
bool did[maxn<<2];
#define lson (t<<1)
#define rson (t<<1|1)
void update(ll t,ll l,ll r,ll k,ll b){
if(!did[t]) segb[t]=b,segk[t]=k,did[t]=1;
else{
ll f1=k*l+b,f2=segk[t]*l+segb[t],f3=k*r+b,f4=segk[t]*r+segb[t];
if(f1<=f2&&f3<=f4) return;
else if(f1>=f2&&f3>=f4) segk[t]=k,segb[t]=b;
else{
ll mid=l+r>>1;
double len=Intersection((double)k,(double)b,(double)segk[t],(double)segb[t]);
if(f1>=f2){
if(len<=mid) update(lson,l,mid,k,b);
else{
update(rson,mid+1,r,segk[t],segb[t]);
segk[t]=k;segb[t]=b;
}
}else{
if(len>mid) update(rson,mid+1,r,k,b);
else{
update(lson,l,mid,segk[t],segb[t]);
segk[t]=k;segb[t]=b;
}
}
}
}
}
ll query(ll t,ll l,ll r,ll x){
ll ans=0;
if(did[t]) ans=max(ans,segk[t]*x+segb[t]);
if(l==r){
return ans;
}
ll mid=l+r>>1;
if(x<=mid) return max(ans,query(lson,l,mid,x));
else return max(ans,query(rson,mid+1,r,x));
}
ll ans[maxn];
int main(){
while(~scanf("%lld%lld",&n,&y)){
memset(did,0,sizeof(did));
for(ll i=1;i<=n;i++) scanf("%lld",&a[i]);
sort(a+1,a+n+1);
a[0]=-y;
ll low=n,g;
update(1,1,y,1,a[n]);
for(ll x=y;x>=1;x--){
ans[x]=INF;
// printf(" x=%d\n",x);
while(low>=1){
g=query(1,1,y,x);
// printf(" low=%lld g=%lld\n",low,g);
if(g<=a[low-1]+y){
ans[x]=min(ans[x],max(g,a[low-1]+y)),low--;
update(1,1,y,n-low+1,a[low]);
// printf(" add x=%d low=%lld k=%lld b=%lld\n",x,low,n-low+1,a[low-1]);
}else{
ans[x]=min(ans[x],max(g,a[low-1]+y));
if(x<y) ans[x]=min(ans[x],ans[x+1]);
break;
}
}
}
for(ll i=1;i<=y;i++) printf("%lld%c",ans[i],i==y?'\n':' ');
}
return 0;
}