寻找段落

给定一个长度为 n 的序列 ,定义 ai为第 i个元素的价值。现在需要找出序列中最有价值的“段落”。段落的定义是长度在 [S,T]之间的连续序列,

最有价值段落是指平均值最大的段落,段落的平均值 = 段落总价值 / 段落长度。

输入格式

第一行一个整数 n (1n105),表示序列长度。

第二行两个整数 S 和 T,表示段落长度的范围在 [S,T]之间(1STn)。

第三行 n 个整数  (10000ai10000),表示每个元素的价值。

输出格式

一个实数,保留 3位小数,表示最优段落的平均值。

输出时每行末尾的多余空格,不影响答案正确性

样例输入

4
3 4
5 3 -3 9

样例输出

3.500

代码:

 1 #include<iostream>
 2 #include<iomanip>
 3 using namespace std;
 4 
 5 double findValue3(int *arr,int n,int len){
 6     double maxdemo=-0xffffff,sum;
 7     for (int i = 1; i <= n-len+1; i++)
 8     {
 9         sum=0;
10         for (int j = i; j < i+len; j++)
11         {
12             sum+=arr[j];
13         }
14         if (sum>maxdemo)
15         {
16             maxdemo=sum;
17         }
18     }
19     return maxdemo/len;    
20 }
21 
22 int main(){
23     int n;
24     cin>>n;
25     int S,T;
26     cin>>S>>T;
27     int *arr = new int[n+1];
28     for (int i = 1; i <= n; i++)
29     {
30         cin>>arr[i];
31     }
32     double sum=0,max=-0xffffff;
33     for (int i = S; i <= T; i++)
34     {
35         double value=findValue3(arr,n,i);
36         if(value>max){
37             max=value;
38         }
39     }
40     cout<<setiosflags(ios::fixed)<<setprecision(3)<<max<<endl;
41 
42 }

 

 

 

#include<iostream>
#include<cstdio>
#include<deque>
#include<cstring>
#define rg register
template<typename T>inline T read(T&x)
{
    T data=0;
    int w=1;
    char ch=getchar();
    while(ch!='-'&&!isdigit(ch))
        ch=getchar();
    if(ch=='-')
        w=-1,ch=getchar();
    while(isdigit(ch))
        data=data*10+ch-'0',ch=getchar();
    return x=data*w;
}
using namespace std;
typedef long long ll;

const int MAXN=1e5+7;
int n,S,T;
int a[MAXN];
ll sum[MAXN]; // prefix sum
int L=1e8,R=-1e8;

deque <int> Q;

inline bool judge(int x)
{
//  cerr<<"judging x="<<x<<endl;
    memset(sum,0,sizeof(sum));
    for(rg int i=1;i<=n;++i)
    {
        sum[i]=sum[i-1]+a[i]-x;
//      clog<<"sum["<<i<<"]= "<<sum[i]<<endl;
    }
    Q.clear();
    for(rg int i=S,p=0;i<=n;++i,++p)
    { // 只有一段不包括本身的区间内合法,就开两个扫描线
        while(!Q.empty()&&sum[Q.back()]>sum[p])
            Q.pop_back();
        Q.push_back(p);
        while(Q.front()<i-T) // 这里不用判空是因为p一定存在
            Q.pop_front();
        if(sum[i]-sum[Q.front()]>=0)
            return 1;
    }
//  cerr<<"failed"<<endl;
    return 0;
}

int main()
{
    read(n);read(S);read(T);
    for(rg int i=1;i<=n;++i)
    {
        read(a[i]);
        a[i]*=1e4;
//      cerr<<"a["<<i<<"]= "<<a[i]<<endl;
        L=min(L,a[i]);
        R=max(R,a[i]);
    }
    while(L<R)
    {
        int M=(L+R+1)>>1;
        if(judge(M))
            L=M;
        else
            R=M-1;
    }
    printf("%.3f",L/1e4);
}

 

posted @ 2020-04-15 11:19  关注我更新论文解读  阅读(60)  评论(0编辑  收藏  举报