T3 期末考试
思维题
题目读着就很摸不到头脑,不知道该用啥算法,但想想暴力反而能找到灵感。
这题暴力该怎么写?这个问题就很难想,该枚举的是什么?
再读几遍题,很容易想到的是,最小不愉快度的决定因素,是所有成绩都出来的时间。
那么如果给定一个时间值,规定所最后一门成绩在这天前出完,是否可以求出最小不愉快度呢?显然可以
now表示天数,求不愉快度方法如下:
ll ans=0,res=0,ned=0;
for(int i=1;i<=n;i++)
if(que[i]<now)
ans+=(ll)(now-que[i])*C;
for(int i=1;i<=m;i++)
{
if(plan[i]<now) res+=now-plan[i];
if(plan[i]>now) ned+=plan[i]-now;
}
if(A>B) ans+=B*ned;
else
if(res>ned) ans+=(ll)A*ned;
else ans+=(ll)A*res+B*(ned-res);
return ans;
那么我们可以枚举天数了!
经测试,由于本人的代码太水,朴素暴力只能得60分。
考虑优化,常用的套路是二分答案。
但是这道题里的天数和最小值显然没有单调关系,那我们就三分查找好了!
while(l+1<r)
{
int mid=(l+r)>>1;
int miid=(mid+r)>>1;
if(cacl(mid)<cacl(miid)) r=miid;
else l=mid;
}
三分的原理很显然,没学过自己看一下应该就会了(不会找yfl巨神)
别忘了开 unsigned long long就行
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll unsigned long long
ll A,B,C;
int n,m,que[100010],plan[100010];
int read()
{
int ans=0,op=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')op=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){ans=ans*10+ch-'0';ch=getchar();}
return ans*op;
}
ll cacl(int now)
{
ll ans=0,res=0,ned=0;
for(int i=1;i<=n;i++)
if(que[i]<now)
ans+=(ll)(now-que[i])*C;
for(int i=1;i<=m;i++)
{
if(plan[i]<now) res+=now-plan[i];
if(plan[i]>now) ned+=plan[i]-now;
}
if(A>B) ans+=B*ned;
else
if(res>ned) ans+=(ll)A*ned;
else ans+=(ll)A*res+B*(ned-res);
return ans;
}
int main()
{
A=read();B=read();C=read();
n=read(),m=read();
int r=0,l=1;
for(int i=1;i<=n;i++) que[i]=read(),r=max(r,que[i]);
for(int i=1;i<=m;i++) plan[i]=read(),r=max(r,plan[i]);
while(l+1<r)
{
int mid=(l+r)>>1;
int miid=(mid+r)>>1;
if(cacl(mid)<cacl(miid)) r=miid;
else l=mid;
}
printf("%lld",min(cacl(l),cacl(r)));
return 0;
}