【BZOJ5090】组题 分数规划
【BZOJ5090】组题
Description
著名出题人小Q的备忘录上共有n道可以出的题目,按照顺序依次编号为1到n,其中第i道题目的难度系数被小Q估计为a_i,难度系数越高,题目越难,负数表示这道题目非常简单。小Q现在要出一套难题,他决定从备忘录中选取编号连续的若干道题目,使得平均难度系数最高。当然,小Q不能做得太过分,一套题目必须至少包含k道题目,因此他不能通过直接选取难度系数最高的那道题目来组成一套题。请写一个程序,帮助小Q挑选平均难度系数最高的题目。
Input
第一行包含两个整数n,k(1<=n<=100000,1<=k<=n),分别表示题目的总量和题数的下界。
第二行包含n个整数a_1,a_2,...,a_n(|a_i|<=10^8),分别表示每道题目的难度系数。
Output
输出一个既约分数p/q或-p/q,即平均难度系数的最大值。
Sample Input
5 3
1 4 -2 -3 6
1 4 -2 -3 6
Sample Output
5/4
题解:傻题,直接二分答案,然后就变成问你有没有一段区间长度>=K且和>0。直接将区间和变成前缀相减,然后维护个前缀最小值即可。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef long long ll; const int maxn=100010; double b[maxn]; int a[maxn],sb[maxn]; ll sa[maxn]; int n,k; ll P,Q,g; inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar(); return ret*f; } ll gcd(ll a,ll b) { return !b?a:gcd(b,a%b); } bool check(double mid) { int i; for(i=1;i<=n;i++) b[i]=b[i-1]+a[i]-mid,sb[i]=(b[i]<b[sb[i-1]])?i:sb[i-1]; for(i=k;i<=n;i++) { if(b[i]-b[sb[i-k]]>0) { P=sa[i]-sa[sb[i-k]],Q=i-sb[i-k]; return 1; } } return 0; } int main() { n=rd(),k=rd(); int i; for(i=1;i<=n;i++) a[i]=rd(),sa[i]=sa[i-1]+a[i]; double l=-1e8,r=1e8,mid; for(i=1;i<=100;i++) { mid=(l+r)/2; if(check(mid)) l=mid; else r=mid; } g=gcd(P,Q); g=g>0?g:-g; if(g) P/=g,Q/=g; printf("%lld/%lld",P,Q); return 0; }
| 欢迎来原网站坐坐! >原文链接<