• [六省联考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;
    }
  • 相关阅读:
    golang中的左值VS右值
    golang指针接收者和值接收者方法调用笔记
    go中如果想要实现别人写的接口,如何保证确实实现了那个接口而不是错过了什么?
    在windows中给git修改默认的编辑器为sublime
    git config 选项
    json包中的Marshal&Unmarshal 文档译本
    go的database/sql库中db.Exce()
    go中导入包的几种方式
    机器学习之分类和聚类的区别
    TP5.0学习笔记
  • 原文地址:https://www.cnblogs.com/charlesss/p/10980907.html
Copyright © 2020-2023  润新知