zoukankan      html  css  js  c++  java
  • [Shoi2017]期末考试

    传送门

    题目抽象一下:

    分为两类:关于科目的不愉快度(A,B)和关于学生的不愉快度(C)

    重点是想到二分 所有科目的结束时间。

    对于超过结束时间的科目,如果B<=A,那么就尽量用B去更改时间,否则用A更改时间,不能再使用A了就再用B去更改。

    而对于学生,小于时间界限i的还要产生C的不愉快度。

    这样做所有情况都可以覆盖到。

    然鹅这道题很容易爆LL啊。

    #include<bits/stdc++.h>
    #define LL long long
    #define N 100003
    #define INF 10000000000000000
    using namespace std;
    LL read()
    {
        LL x=0,f=1;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x*f;
    }
    LL maxx=-1,minn=INF;
    int t[N],b[N];
    int n,m;
    LL A,B,C;
    LL stu[N],ke[N];
    LL k1=0,k2=0,s=0;//满足时间的科目,不满足时间的科目,满足时间的学生 个数
    LL sum1=0,sum2=0,sum3=0;//满足时间的科目,不满足时间的科目,满足时间的学生 个数*时间 
    LL ans=INF;
    void work1()
    {
        LL res=0;
        for(int i=1;i<=n;++i)
          if((LL)t[i]<maxx)res+=(LL)(maxx-t[i])*(LL)C;
        printf("%lld
    ",res);
    }
    void work2()
    {
        for(int i=100000;i>=1;--i)
        {
            LL res=0;
            sum1-=ke[i]*i;k1-=ke[i];
            sum2+=ke[i]*i;k2+=ke[i];
            sum3-=stu[i]*i;s-=stu[i];
            if(i>minn)continue;
            if(!sum2)continue;
            if(A<B)
            {
                LL p=k1*i-sum1;//前面满足的 
                LL q=sum2-k2*i;//后面不满足的
                res+=min(p,q)*A; 
                q-=min(p,q);
                if(q)res+=q*B;
            }
            else 
            {
                LL q=sum2-k2*i;//后面不满足的
                res+=q*B;
            }
            ans=min(ans,res);
        }
        printf("%lld
    ",ans);
    }
    int main()
    {
        freopen("exam.in","r",stdin);
        freopen("exam.out","w",stdout);
        A=read(),B=read(),C=read();
        n=read(),m=read();
        for(int i=1;i<=n;++i)t[i]=read(),stu[t[i]]++,s++,sum3+=t[i],minn=min(minn,(LL)t[i]);
        for(int i=1;i<=m;++i)b[i]=read(),ke[b[i]]++,k1++,sum1+=b[i],maxx=max(maxx,(LL)b[i]);
        if(A==1000000000&&B==1000000000&&C<=100){work1();return 0;}
        if(C==10000000000000000){work2();return 0;}
        sort(t+1,t+1+n);sort(b+1,b+1+m);
        for(int i=100000;i>=1;--i)
        {
            LL res=0;
            sum1-=ke[i]*i;k1-=ke[i];
            sum2+=ke[i]*i;k2+=ke[i];
            sum3-=stu[i]*i;s-=stu[i];
            if(!sum2)continue;
            if(A<B)
            {
                LL p=k1*i-sum1;//前面满足的 
                LL q=sum2-k2*i;//后面不满足的
                res+=min(p,q)*A; 
                q-=min(p,q);
                if(q)res+=q*B;
            }
            else 
            {
                LL q=sum2-k2*i;//后面不满足的
                res+=q*B;
            }
            res+=(s*i-sum3)*C;
            ans=min(ans,res);
        }
        printf("%lld
    ",ans);
    } 
    View Code
  • 相关阅读:
    lua -- encode and decode
    lua二进制操作函数
    linux C++多线程使用pthread_cond 条件变量
    linux c 多线程编程--互斥锁与条件变量
    linux C--多线程基本概念及API函数
    linux C多线程编程
    2.5 linux C 进程与多线程入门--(5)使用互斥量进行同步
    linux C多线程编程入门(基本API及多线程的同步与互斥)
    2.4 linux C 进程与多线程入门--(4)简单多线程程序
    2.3 linux C 进程与多线程入门--(3)信号
  • 原文地址:https://www.cnblogs.com/yyys-/p/11544228.html
Copyright © 2011-2022 走看看