BZOJ5090: [Lydsy1711月賽]組題(01分數規劃)
阿新 • • 發佈:2018-11-17
5090: [Lydsy1711月賽]組題
Time Limit: 1 Sec Memory Limit: 256 MBSubmit: 785 Solved: 186
[Submit][Status][Discuss]
Description
著名出題人小Q的備忘錄上共有n道可以出的題目,按照順序依次編號為1到n,其中第i道題目的難度係數被小Q估計 為a_i,難度係數越高,題目越難,負數表示這道題目非常簡單。小Q現在要出一套難題,他決定從備忘錄中選取編 號連續的若干道題目,使得平均難度係數最高。當然,小Q不能做得太過分,一套題目必須至少包含k道題目,因此 他不能通過直接選取難度係數最高的那道題目來組成一套題。請寫一個程式,幫助小Q挑選平均難度係數最高的題 目。Input
Output
輸出一個既約分數p/q或-p/q,即平均難度係數的最大值。
Sample Input
5 31 4 -2 -3 6
Sample Output
5/4HINT
Source
思路:01分數規劃,二分平均值,然後就是求最大的連續的長度不小於K的值,然後由於是需要輸出分子分母形式,我們在二分的同時記錄“和”與“長度”,最後約分輸出即可。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) #define ll long long using namespace std; const int maxn=100010; int a[maxn],N,K; double b[maxn]; ll A,B,sum[maxn]; bool check(double Mid) { rep(i,1,N) b[i]=b[i-1]+a[i]-Mid; int pos=0; rep(i,K,N) { if(b[i]-b[pos]>=0){ A=sum[i]-sum[pos]; B=i-pos; return true; } if(b[i-K+1]<b[pos]) pos=i-K+1; }return false; } int main() { scanf("%d%d",&N,&K); double L=-100000000,R=100000000,Mid; int num=40; rep(i,1,N) scanf("%d",&a[i]),; rep(i,1,N) sum[i]=sum[i-1]+a[i]; while(num--){ Mid=(L+R)/2; if(check(Mid)) L=Mid; else R=Mid; } if(A<0) putchar('-'),A=abs(A); ll g=__gcd(A,B); printf("%lld/%lld\n",A/g,B/g); return 0; }
但是不知道為什麼我自己的check函式是WA的,難道是delta一直做加減法引起的精度問題?
bool check(double Mid) { rep(i,1,N) b[i]=(double)a[i]-Mid; int head=1; double delta=0; rep(i,1,N) { delta+=b[i]; while(i-head+1>K&&b[head]<0) delta-=b[head++]; if(i-head+1>=K&&delta>=0){ A=sum[i]-sum[head-1]; B=i-head+1; return true; } }return false; }