【三分+枚举】LNOI2017 d1t1 期末考试
生活随笔
收集整理的這篇文章主要介紹了
【三分+枚举】LNOI2017 d1t1 期末考试
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述: 有n位同學,每位同學都參加了全部的m門課程的期末考試,都在焦急的等待成績的公布。第i位同學希望在第ti天或之前得知所有課程的成績。如果在第ti天,有至少一門課程的成績沒有公布,他就會等待最后公布成績的課程公布成績,每等待一天就會產生C不愉快度。對于第i門課程,按照原本的計劃,會在第bi天公布成績。有如下兩種操作可以調整公布成績的時間: 1.將負責課程X的部分老師調整到課程Y,調整之后公布課程X成績的時間推遲一天,公布課程Y成績的時間提前一天;每次操作產生A不愉快度。 2.增加一部分老師負責學科Z,這將導致學科Z的出成績時間提前一天;每次操作產生B不愉快度。 上面兩種操作中的參數X,Y,Z均可任意指定,每種操作均可以執行多次,每次執行時都可以重新指定參數。現在希望你通過合理的操作,使得最后總的不愉快度之和最小 題解: 正解請見此處(先用三分縮小范圍再枚舉,因為函數圖像可能不是平滑的,會有“鋸齒”):https://www.luogu.org/wiki/show?name=%E9%A2%98%E8%A7%A3+P3745 討論請見此處8.30關于單調性的探究:http://www.cnblogs.com/algonote/p/7441725.html 下面是我的60分做法:(要是這道題也沒搞出來我就只剩20分了)
由于這道題比較復雜,有多個變量,所以不太可能直接出答案(咋不說是因為你太弱了呢),那么就應該是枚舉從第1天(全部調整,老師不愉悅度最大)到第Max{b}天(不調整,老師不愉悅度為0)之間所有的不愉悅度了。
假設成績在第d天公布,那么這時學生的不愉快度很好求(用前綴和),問題是老師的最小不愉快度如何快速求解。
出成績的時間只取決于最后一課出成績的時間,所以想要在第d天出成績的話,就要讓最后一課出成績的時間小于等于第d天。
讓最后一課提前一天有兩種方式,A<B應該優先考慮方式一,A>B應該優先考慮方式二。
但是注意方式一的使用次數是有限制的,不能讓課程出成績時間由小于等于第x天變為大于第x天,因為這樣就需要額外使用方式二將它的成績時間移回第x天,得不償失。
1 long long p[100010]; 2 long long getsad(int d) 3 { 4 memcpy(p,o,m);//保留原數組o 5 long long unhappy=0; 6 for (;;) 7 { 8 sort(p,p+m); 9 if (p[m]/*最晚一科出成績的時間*/<=d) return unhappy; 10 if (a<b&&p[0]/*最早一科出成績的時間*/<d) 11 { 12 //執行方案一 13 p[m]--;p[0]++; 14 unhappy+=a; 15 } 16 else 17 { 18 //執行方案二 19 p[m]--; 20 unhappy+=b; 21 } 22 } 23 }?
可是這樣時間復雜度很高,為$O(n^3)$。
注意第x天前和第x天后的出成績時間分別具有相同的性質,所以我們可以把他們分別組合起來。
如果A<B,那么就應盡可能多得用方案一,剩余的再用方案二。
如果A>B,那么就一直用方案二。
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 using namespace std; 5 int a,b,n,m,t[100010],o[100010]; 6 long long stusad=0,ans=1e18,c,g[100010]; 7 long long getsad(int d) 8 { 9 long long front=0,back=0; 10 for (int i=0;i<m;i++) 11 { 12 if (o[i]<d) 13 front+=d-o[i]; 14 else 15 back+=o[i]-d; 16 } 17 if (a<b) 18 { 19 if (front>back) 20 return back*a; 21 else 22 return front*a+(back-front)*b; 23 } 24 else 25 return back*b; 26 } 27 int main() 28 { 29 scanf("%d%d%lld%d%d",&a,&b,&c,&n,&m); 30 for (int i=0;i<n;i++) scanf("%d",&t[i]); 31 for (int i=0;i<m;i++) scanf("%d",&o[i]); 32 if (c==1e16) 33 { 34 sort(t,t+n); 35 ans=getsad(t[0]); 36 } 37 else 38 { 39 sort(o,o+m); 40 for (int i=0;i<n;i++) 41 for (int j=t[i]+1;j<=o[m-1];j++) 42 g[j]+=c; 43 for (int i=1;i<=o[m-1];i++) 44 { 45 stusad+=g[i]; 46 ans=min(ans,stusad+getsad(i)); 47 } 48 } 49 printf("%lld",ans); 50 return 0; 51 }?
這樣復雜度就降到了$O(n^2)$
轉載于:https://www.cnblogs.com/algonote/p/6790878.html
總結
以上是生活随笔為你收集整理的【三分+枚举】LNOI2017 d1t1 期末考试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MongoDB对文档的操作
- 下一篇: 磁盘问题定位与解决