bzoj4868 [Shoi2017]期末考試
阿新 • • 發佈:2017-12-31
個學生 希望 部分 cin 由於 n) 重新 hint tin
第一行三個非負整數A,B,C,描述三種不愉快度,詳見【問題描述】;
第二行兩個正整數n,m(1≤n,m≤105),分別表示學生的數量和課程的數量;
第三行n個正整數ti,表示每個學生希望的公布成績的時間;
第四行m個正整數bi,表示按照原本的計劃,每門課程公布成績的時間。
1<=N,M,Ti,Bi<=100000,0<=A,B,C<=100000
4 5
5 1 2 3
1 1 2 3 3
同學 1 希望在第 5 天或之前出成績,所以不會產生不愉快度;
同學 2 希望在第 1 天或之前出成績,產生的不愉快度為 (3 - 1) * 2 = 4;
同學 3 希望在第 2 天或之前出成績,產生的不愉快度為 (3 - 2) * 2 = 2;
同學 4 希望在第 3 天或之前出成績,所以不會產生不愉快度;
不愉快度之和為 4 + 2 = 6 。
Description
有n位同學,每位同學都參加了全部的m門課程的期末考試,都在焦急的等待成績的公布。第i位同學希望在第ti天或之前得知所.有.課程的成績。如果在第ti天,有至少一門課程的成績沒有公布,他就會等待最後公布成績的課程公布成績,每等待一天就會產生C不愉快度。對於第i門課程,按照原本的計劃,會在第bi天公布成績。有如下兩種操作可以調整公布成績的時間:1.將負責課程X的部分老師調整到課程Y,調整之後公布課程X成績的時間推遲一天,公布課程Y成績的時間提前一天;每次操作產生A不愉快度。2.增加一部分老師負責學科Z,這將導致學科Z的出成績時間提前一天;每次操作產生B不愉快度。上面兩種操作中的參數X,Y,Z均可任意指定,每種操作均可以執行多次,每次執行時都可以重新指定參數。現在希望你通過合理的操作,使得最後總的不愉快度之和最小,輸出最小的不愉快度之和即可Input
Output
輸出一行一個整數,表示最小的不愉快度之和。Sample Input
100 100 24 5
5 1 2 3
1 1 2 3 3
Sample Output
6由於調整操作產生的不愉快度太大,所以在本例中最好的方案是不進行調整; 全部 的5門課程中,最慢的在第 3 天出成績;同學 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]期末考試