[六省联考2017]期末考试

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;
}
原文地址:https://www.cnblogs.com/charlesss/p/10980907.html