1. 程式人生 > >bzoj4868 [Shoi2017]期末考試

bzoj4868 [Shoi2017]期末考試

個學生 希望 部分 cin 由於 n) 重新 hint tin

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

正解:模擬+單調指針。

傻逼題。首先對兩個數組排序,分別記錄前綴和。

枚舉最後一個公布成績的時間,並用前綴和$O(1)$計算出貢獻,取最小的$ans$即可。

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define inf (1LL<<61)
 6 #define N (100005)
 7 
 8 using namespace std;
 9 
10 ll sum[N],pre[N],A,B,C,ans;
11 int t[N],b[N],n,m;
12 
13 il int gi(){
14   RG int x=0,q=1; RG char ch=getchar();
15   while ((ch<0 || ch>9) && ch!=-) ch=getchar();
16   if (ch==-) q=-1,ch=getchar();
17   while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar();
18   return q*x;
19 }
20 
21 int main(){
22 #ifndef ONLINE_JUDGE
23   freopen("test.in","r",stdin);
24   freopen("test.out","w",stdout);
25 #endif
26   cin>>A>>B>>C>>n>>m,ans=inf;
27   for (RG int i=1;i<=n;++i) t[i]=gi();
28   for (RG int i=1;i<=m;++i) b[i]=gi();
29   sort(t+1,t+n+1),reverse(t+1,t+n+1);
30   sort(b+1,b+m+1),reverse(b+1,b+m+1);
31   for (RG int i=1;i<=n;++i) sum[i]=sum[i-1]+t[i];
32   for (RG int i=1;i<=m;++i) pre[i]=pre[i-1]+b[i];
33   for (RG int tim=b[1],p1=0,p2=0;tim>=b[m];--tim){
34     while (p1<n && t[p1+1]>=tim) ++p1;
35     while (p2<m && b[p2+1]>=tim) ++p2;
36     if(1LL*(n-p1)*tim-sum[n]+sum[p1]>=inf/C) continue;
37     RG ll tmp,res,rem;
38     if (B<=A){
39       if (pre[p2]-1LL*p2*tim<inf/B) res=(pre[p2]-1LL*p2*tim)*B;
40       else continue;
41     } else{
42       tmp=pre[p2]-1LL*p2*tim;
43       rem=1LL*(m-p2)*tim-pre[m]+pre[p2];
44       if (min(tmp,rem)>=inf/A) continue;
45       res=min(tmp,rem)*A+(tmp>rem?tmp-rem:0)*B;
46     }
47     ans=min(ans,res+(1LL*(n-p1)*tim-sum[n]+sum[p1])*C);
48   }
49   cout<<ans; return 0;
50 }

bzoj4868 [Shoi2017]期末考試