zoukankan      html  css  js  c++  java
  • [BZOJ4868][六省联考2017]期末考试(三分)

    4868: [Shoi2017]期末考试

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 964  Solved: 439
    [Submit][Status][Discuss]

    Description

    有n位同学,每位同学都参加了全部的m门课程的期末考试,都在焦急的等待成绩的公布。第i位同学希望在第ti天
    或之前得知所.有.课程的成绩。如果在第ti天,有至少一门课程的成绩没有公布,他就会等待最后公布成绩的课程
    公布成绩,每等待一天就会产生C不愉快度。对于第i门课程,按照原本的计划,会在第bi天公布成绩。有如下两种
    操作可以调整公布成绩的时间:1.将负责课程X的部分老师调整到课程Y,调整之后公布课程X成绩的时间推迟一天
    ,公布课程Y成绩的时间提前一天;每次操作产生A不愉快度。2.增加一部分老师负责学科Z,这将导致学科Z的出成
    绩时间提前一天;每次操作产生B不愉快度。上面两种操作中的参数X,Y,Z均可任意指定,每种操作均可以执行多次
    ,每次执行时都可以重新指定参数。现在希望你通过合理的操作,使得最后总的不愉快度之和最小,输出最小的不
    愉快度之和即可

    Input

    第一行三个非负整数A,B,C,描述三种不愉快度,详见【问题描述】;
    第二行两个正整数n,m(1≤n,m≤105),分别表示学生的数量和课程的数量;
    第三行n个正整数ti,表示每个学生希望的公布成绩的时间;
    第四行m个正整数bi,表示按照原本的计划,每门课程公布成绩的时间。
    1<=N,M,Ti,Bi<=100000,0<=A,B,C<=100000

    Output

    输出一行一个整数,表示最小的不愉快度之和。

    Sample Input

    100 100 2
    4 5
    5 1 2 3
    1 1 2 3 3

    Sample Output

    6
    由于调整操作产生的不愉快度太大,所以在本例中最好的方案是不进行调整; 全部
    5 的门课程中,最慢的在第 3 天出成绩;
    同学 1 希望在第 5 天或之前出成绩,所以不会产生不愉快度;
    同学 2 希望在第 1 天或之前出成绩,产生的不愉快度为 (3 - 1) * 2 = 4;
    同学 3 希望在第 2 天或之前出成绩,产生的不愉快度为 (3 - 2) * 2 = 2;
    同学 4 希望在第 3 天或之前出成绩,所以不会产生不愉快度;
    不愉快度之和为 4 + 2 = 6 。

    HINT

     存在几组数据,使得C = 10 ^ 16

    Source

    [Submit][Status][Discuss]

    听说可以直接线性贪心,不过网上大部分做法都是三分。

    显然最终不愉快度关于出成绩的时间是一个下凸的单峰函数,直接三分就好了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define rep(i,l,r) for (int i=l; i<=r; i++)
    typedef long long ll;
    using namespace std;
    
    const int N=100100;
    ll a,b,c,mn,ti[N],bi[N];
    int n,m;
    
    ll jud(ll x){
    	ll res=0;
    	if (a<b){
    		ll tmp1=0,tmp2=0;
    		rep(i,1,m)
    			if (x<bi[i]) tmp1+=bi[i]-x; else tmp2+=x-bi[i];
    		if (tmp2>=tmp1) res+=tmp1*a; else res+=tmp2*a+(tmp1-tmp2)*b;
    	}else rep(i,1,m) if (x<bi[i]) res+=(bi[i]-x)*b;
    	rep(i,1,n) if (x>ti[i]) res+=(x-ti[i])*c;
    	return res;
    }
    
    ll solve(){
    	ll l=1,r=100000;
    	while (l+2<r){
    		ll mid1=(2*l+r)/3,mid2=(l+2*r)/3,t1=jud(mid1),t2=jud(mid2);
    		if (t1==t2) l=mid1,r=mid2;
    		else if (t1<t2) r=mid2; else l=mid1;
    	}
    	ll t1=jud(l),t2=jud(r),t3=jud((2*l+r)/3),t4=jud((l+2*r)/3);
    	return min(min(t1,t2),min(t3,t4));
    }
    
    int main(){
    	freopen("exam.in","r",stdin);
    	freopen("exam.out","w",stdout);
    	scanf("%lld%lld%lld",&a,&b,&c);
    	scanf("%d%d",&n,&m);
    	rep(i,1,n) scanf("%lld",&ti[i]);
    	rep(i,1,m) scanf("%lld",&bi[i]);
    	if (c==1e16){
    		mn=1e17;
    		rep(i,1,n) mn=min(mn,ti[i]);
    		printf("%lld
    ",jud(mn));
    		return 0;   
    	}
    	printf("%lld
    ",solve());
    	return 0;
    }
    
  • 相关阅读:
    Populating Next Right Pointers in Each Node II
    Populating Next Right Pointers in Each Node
    Construct Binary Tree from Preorder and Inorder Traversal
    Construct Binary Tree from Inorder and Postorder Traversal
    Path Sum
    Symmetric Tree
    Solve Tree Problems Recursively
    632. Smallest Range(priority_queue)
    609. Find Duplicate File in System
    poj3159最短路spfa+邻接表
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8656660.html
Copyright © 2011-2022 走看看