bzoj5090组题 分数规划

组题

Time Limit: 1 Sec  Memory Limit: 256 MB
Submit: 542  Solved: 114
[Submit][Status][Discuss]

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

Sample Output

5/4

HINT

 

Source

题解:

  二分答案,判断有没有长度大于等于k的正数段即可,选得越少答案越大。

 1 #include<cstring>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cstdio>
 6 
 7 #define ll long long
 8 using namespace std;
 9 inline int read()
10 {
11     int x=0,f=1;char ch=getchar();
12     while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();}
13     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
14     return x*f;
15 }
16 
17 int n,k,L,R,a[100005];
18 double s[100005];
19 ll A,G,len;
20 ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);}
21 bool judge(double mid)
22 {
23     int p=0;double mn=100000000000000,mx=0;bool flag=0;
24     for (int i=1;i<=n;i++)
25     {
26         s[i]=s[i-1]+1.0*a[i]-mid;
27         if (i>=k&&mn>s[i-k]) mn=s[i-k],p=i-k;
28         if (s[i]-mn>=mx){mx=s[i]-mn;L=p;R=i;flag=1;}
29     }
30     return flag;
31 }
32 int main()
33 {
34     n=read();k=read();
35     for (int i=1;i<=n;i++) a[i]=read();
36     double l=-100000005,r=100000005;
37     while (r-l>0.000001)
38     {
39         double mid=(l+r)/2;
40         if (judge(mid)) l=mid;else r=mid;
41     }
42     for (int i=L+1;i<=R;i++) A+=(ll)a[i];len=R-L;
43     G=gcd(abs(A),len);
44     A/=G;len/=G;
45     printf("%lld/%lld",A,len);
46 }
原文地址:https://www.cnblogs.com/fengzhiyuan/p/8119343.html