• UVALive 4850 Installations


      题目大意:有若干个任务,每个任务耗时si,期限为di,同一时间只能做一个任务。对于一个任务,惩罚值为max(0,完成时间-期限)。问怎么安排,使(最大惩罚值+次大惩罚值)最小,O(n^2)。

      如果没有次大惩罚值,就是一个很显然的贪心了:把任务按di排序,di相同按si排序,一路平推过去。

      这样可以保证最大值最小,但不能保证(最大+次大)最小。好在这题有十分良心的样例:

     

      仔细观察一下样例,你会发现:基本上也是按照上面的逻辑做任务,但J2和J6换了一个位置。

      还有一件非常巧合的事情:J2和J6就是答案。

      观察一下完全按照上面逻辑做的情况,发现答案是8,最大值是J6(5),次大值是J2(3)。

      然后把J2换到J6右边,就变成最大值J2(6),次大值J6(1)。

      提示我们可以通过把一个前面的拿出来,扔到原先最大/次大的后一个去。

      分析一下这样做的结果:后半截不变,拿出来的变成最大值,原来的最大值、次大值减小并作为次大值,最终结果可能会比原答案小。

      看一下数据,枚举,O(n^2)就可以了。

      为什么只拿一个就可以了呢?因为拿两个就肯定比不拿要大了(第一次拿出的超过原次大值,第二次的超过原来的最大值)。

      要不是有样例我一年都想不出这个

    #include    <iostream>
    #include    <cstdio>
    #include    <cstdlib>
    #include    <algorithm>
    #include    <vector>
    #include    <cstring>
    #include    <queue>
    #include    <complex>
    #include    <stack>
    #define LL long long int
    #define dob double
    #define FILE "4850"
    using namespace std;
    
    const int N = 100010;
    struct Pair{
      int t,r;
      bool operator <(const Pair &p)const{
        if(r==p.r)return t<p.t;
        return r<p.r;
      }
    }A[N];
    int n,id,Ans,L[N],R[N];
    
    inline int gi(){
      int x=0,res=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')res*=-1;ch=getchar();}
      while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
      return x*res;
    }
    
    inline int getmxp(){
      int sum=0,mxp=0,nmxp=0;id=0;
      for(int i=R[0],p;i<=n;i=R[i]){
        sum+=A[i].t;p=max(0,sum-A[i].r);
        if(p>=mxp)nmxp=mxp,mxp=p,id=i;
        else if(p>=nmxp)nmxp=p,id=i;
      }
      return mxp+nmxp;
    }
    
    inline void solve(){
      n=gi();R[0]=1;L[n+1]=n;
      for(int i=1;i<=n;++i)
        A[i].t=gi(),A[i].r=gi(),L[i]=i-1,R[i]=i+1;
      sort(A+1,A+n+1);Ans=getmxp();
      if(!Ans){printf("0
    ");return;}
      for(int i=R[0],j=id;i!=j;i=R[i]){
        int l=L[i],r=R[i];
        R[l]=r;R[i]=R[j];R[j]=i;
        Ans=min(Ans,getmxp());
        R[j]=R[i];R[l]=i;R[i]=r;
      }
      printf("%d
    ",Ans);
    }
    
    int main()
    {
      freopen(FILE".in","r",stdin);
      freopen(FILE".out","w",stdout);
      int Case=gi();while(Case--)solve();
      fclose(stdin);fclose(stdout);
      return 0;
    }
    Installations
  • 相关阅读:
    Centos系统python2.x升级python3.x
    VirtualBox安装Ghost XP
    VirtualBox检查更新失败解决办法
    PyDev+eclipse的编码问题
    redhat开启linux server
    使用VNC实现多用户登录linux系统
    使用webdav实现文档共享
    各类软件使用说明
    linux安装apache软件的过程
    JavaScript获取DOM元素位置和尺寸大小
  • 原文地址:https://www.cnblogs.com/fenghaoran/p/7663223.html
Copyright © 2020-2023  润新知