博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ4868: [Shoi2017]期末考试
阅读量:5887 次
发布时间:2019-06-19

本文共 2643 字,大约阅读时间需要 8 分钟。

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 936  Solved: 426
[][][]

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

 

考场上还是静不下心来

总感觉这题是个dp

然后直接弃掉了。

其实还是挺简单的。

我们钦定一个试卷被批完的最晚时间

然后通过二分+前缀和计算出学生的不愉快度

再利用二分+后缀和计算出让最后一个被批完的试卷的时间满足要求的不愉快的

两者求和取最小值就可以了

 

这道题的关键是看出学生不满意度和试卷被批完的时间之间的单调关系

然后要想到枚举时间

#include
#include
#include
#define int unsigned long long using namespace std;const int MAXN=1e5+10;const int INF=1e19;inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){
if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f;}int A,B,C;int N,M;int t[MAXN],b[MAXN];int sumt[MAXN],sumb[MAXN];//t的前缀与b的后缀 int limit,ans=INF;main(){ #ifdef WIN32 freopen("a.in","r",stdin); #endif A=read();B=read();C=read(); N=read();M=read(); for(int i=1;i<=N;i++) t[i]=read(); for(int i=1;i<=M;i++) b[i]=read(),limit=max(limit,b[i]); sort(t+1,t+N+1); sort(b+1,b+M+1); for(int i=1;i<=N;i++) sumt[i]=t[i]+sumt[i-1]; for(int i=M;i>=1;i--) sumb[i]=b[i]+sumb[i+1]; for(int i=1;i<=limit;i++) { int l=1,r=N,ans1=0,ans2=0,now=0; while(l<=r) { int mid=l+r>>1; if(t[mid]
>1; if(b[mid]>i) ans2=mid,r=mid-1; else l=mid+1; } if(ans1!=0) now+=(ans1*i-sumt[ans1])*C; if(ans2!=0) { int need=(sumb[ans2]-(M-ans2+1)*i); if(A>=B) now+=need*B; else { int have=(ans2-1)*i-(sumb[1]-sumb[ans2]); if(have>=need) now+=need*A; else now+=have*A+(need-have)*B; } } ans=min(ans,now); } printf("%lld",ans); return 0;}

 

转载地址:http://ckgix.baihongyu.com/

你可能感兴趣的文章
cxf 整合 spring 时 java.lang.VerifyError异常
查看>>
javascript中工厂模式
查看>>
MFC GetDlgItemText 失败
查看>>
NSString NSMutableString
查看>>
个人练习集锦
查看>>
log4net 将日志写入数据库
查看>>
springboot之启动方式
查看>>
初次安装git配置用户名和邮箱及密钥
查看>>
微服务架构盛行的时代,你需要了解点 Spring Boot
查看>>
6.1(续)索引、索引组织表--Oracle模式对象
查看>>
工作5年左右的程序员如何在职业瓶颈期内快速提升自己的身价?提升后如何有效变现自己的高质量技能?...
查看>>
动画 球
查看>>
C++中的堆,栈,静态内存区,常量区
查看>>
动态SQL实现与注意事项(有返回值与无返回值动态SQL 实现)
查看>>
java struts2 debug
查看>>
解析 PHP 中 session 的实现原理以及大网站应用应该注意的问题
查看>>
[转].net mvc + vuejs 的项目结构
查看>>
Centos7安装Redis
查看>>
简单够用的设计
查看>>
javascript权威指南--学习笔记
查看>>