1. 程式人生 > >[luogu] P3745 [六省聯考2017]期末考試 (貪心)

[luogu] P3745 [六省聯考2017]期末考試 (貪心)

還需要 數量 貪心 我們 max clu 網上 增加 記錄

P3745 [六省聯考2017]期末考試

題目描述

\(n\) 位同學,每位同學都參加了全部的 \(m\) 門課程的期末考試,都在焦急的等待成績的公布。

\(i\) 位同學希望在第 \(t_i\)? 天或之前得知所有課程的成績。如果在第 \(t_i\) 天,有至少一門課程的成績沒有公布,他就會等待最後公布成績的課程公布成績,每等待一天就會產生 \(C\) 不愉快度。

對於第 \(i\) 門課程,按照原本的計劃,會在第 \(b_i\)? 天公布成績。

有如下兩種操作可以調整公布成績的時間:

  1. 將負責課程 \(X\) 的部分老師調整到課程 \(Y\),調整之後公布課程 \(X\) 成績的時間推遲一天,公布課程 \(Y\)
    成績的時間提前一天;每次操作產生 \(A\) 不愉快度。
  2. 增加一部分老師負責學科 \(Z\),這將導致學科 \(Z\) 的出成績時間提前一天;每次操作產生 \(B\) 不愉快度。

上面兩種操作中的參數 \(X, Y, Z\) 均可任意指定,每種操作均可以執行多次,每次執行時都可以重新指定參數。

現在希望你通過合理的操作,使得最後總的不愉快度之和最小,輸出最小的不愉快度之和即可。

輸入輸出格式

輸入格式:

第一行三個非負整數 \(A, B, C\),描述三種不愉快度,詳見【題目描述】;
第二行兩個正整數 \(n, m\),分別表示學生的數量和課程的數量;
第三行 \(n\) 個正整數 \(t_i\)

,表示每個學生希望的公布成績的時間;
第四行 \(m\) 個正整數 \(b_i\),表示按照原本的計劃,每門課程公布成績的時間。

輸出格式:

輸出一行一個整數,表示最小的不愉快度之和。

輸入輸出樣例

輸入樣例#1: 復制

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

輸出樣例#1: 復制

6

輸入樣例#2: 復制

3 5 4
5 6
1 1 4 7 8
2 3 3 1 8 2

輸出樣例#2: 復制

33

說明

【樣例 1 說明】

由於調整操作產生的不愉快度太大,所以在本例中最好的方案是不進行調整; 全部

5 的門課程中,最慢的在第 3 天出成績;

同學 1 希望在第 5 天或之前出成績,所以不會產生不愉快度;

同學 2 希望在第 1 天或之前出成績,產生的不愉快度為 (3 ? 1) ? 2 = 4;

同學 3 希望在第 2 天或之前出成績,產生的不愉快度為 (3 ? 2) ? 2 = 2;

同學 4 希望在第 3 天或之前出成績,所以不會產生不愉快度;

不愉快度之和為 4 + 2 = 6 。

技術分享圖片

題解

整個題目的貪心在於如何處理\(A<B\),因為,\(A\)的使用會伴隨著一門科目的推遲,也就是說\(A\)的使用次數是有限的。

註意到整個題目的意思就是要我們提前天數,那麽我們可以考慮枚舉天數,網上使用三分和二分的大佬們實在是太巨辣,我只會\(O(n)\)
那麽當\(A<B\)的時候,我們就根據天數的推移用前綴和統計一下能有幾天可以推遲,然後計算\(A\)使用的次數,不夠的再用\(B\)提前。
整個難點就在於學生和科目隨時間的線性變化,要自己理一理。
我們用一個桶記錄學生忍耐的時間,另一個記錄科目出成績的時間。
那麽隨時間線性變化便是,
每往後一天,記錄這天前有多少科目是可以推遲的,對於推遲的貢獻,
有多少學生是開始忍耐不了的。
有多少科目是還需要提前的,對於提前一共要多少天。
自己好好想一下。不懂可以看代碼。

Code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#define ll unsigned long long
using namespace std;
const ll MAXN=1e6+5;
ll a,b,c,n,m,N,M,sum,ans=1e18,tot;
ll ti[MAXN],bi[MAXN],bac1[MAXN],bac2[MAXN];
ll s,ss,tt,t1,t2,t3;
ll read(){
    ll x=0,w=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*w;
}
int main(){
    a=read();b=read();c=read();
    n=read();t2=m=read();
    for(ll i=1;i<=n;i++)ti[i]=read(),bac1[ti[i]]++;
    for(ll i=1;i<=m;i++)bi[i]=read(),bac2[bi[i]]++,ss+=bi[i];
    for(ll i=1;i<=100000;i++){
        //tt當前不能忍受的人的天數,ss當前需要提前的天數,s是當前可以做貢獻的天數
        tt+=bac1[i-1]+t1;t1+=bac1[i-1];
        t2-=bac2[i];ss-=bac2[i]+t2;
        s+=bac2[i-1]+t3;t3+=bac2[i-1];
        sum=tt*c;tot=0;
        if(a<b){
            tot=min(ss,s);sum+=min(ss,s)*a;
        }
        sum=sum+max((ss-tot),(ll)0)*b;
        ans=min(ans,sum);
    }
    cout<<ans<<endl;
    return 0;
}

[luogu] P3745 [六省聯考2017]期末考試 (貪心)