• 洛谷1419 寻找段落(单调队列)


    洛谷1419 寻找段落

    本题地址: http://www.luogu.org/problem/show?pid=1419

    题目描述

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

    输入输出格式

    输入格式:

    第一行一个整数n,表示序列长度。
    第二行两个整数S和T,表示段落长度的范围,在[S,T]之间。
    第三行到第n+2行,每行一个整数表示每个元素的价值指数。

    输出格式:

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

    输入输出样例

    输入样例#1:

    3

    2 2

    3

    -1

    2

    输出样例#1:

    1.000

    说明

    【数据范围】
    对于30%的数据有n<=1000。
    对于100%的数据有n<=100000,1<=S<=T<=n,-10000<=价值指数<=10000。
    【题目来源】
    tinylic改编

    【思路】

      二分+单调队列。

      首先二分最大平均值x。

      那么问题就转化为:是否存在一个区间的的平均值大于x。这个问题可以类比于UVa11090 Going in Cycle!!,我们将a全部减去x,问题进一步转化为判断是否存在一个长度在s..t范围内的区间它的和为正,如果有说明还有更大的平均值。

      如何判断?单调队列。

      令sum表示a-x的前缀和。则上述条件可以变化为sumi-sumj>=0,对于i我们需要找到指定区间内的最大sumj。

      单调队列维护序号在i-t到i-s的区间,保持sum的递增序,求区间最大值,判断与0的关系即可。

    【代码】

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 using namespace std;
     5 
     6 const int maxn = 100000+10;
     7 
     8 int A[maxn];
     9 int n,s,t;
    10 
    11 double sum[maxn];
    12 int q[maxn],front,rear;
    13 bool can(double x) {
    14     sum[0]=0;
    15     for(int i=1;i<=n;i++) sum[i] = sum[i-1]+A[i]-x;
    16     front=1; rear=0;                  //初始化单调队列为空 
    17     for (int i = 1; i <= n; i++) {  
    18         if (i >= s) {                 //足够s个  //front为在i-t..i-s区间内的最小值
    19             while (rear >= front && sum[i - s] < sum[q[rear]])  rear--;  
    20             q[++rear] = i - s;        //入队区间起点-1 
    21         }
    22         if (front <= rear && q[front] < i - t) front++;  //维护区间i-t  
    23         if (front <= rear && sum[i] - sum[q[front]] >= 0) return true; //有大于0的区间和说明最大平均值还可以更大   
    24     }
    25     return false;
    26 }
    27 
    28 int main() {
    29     scanf("%d%d%d",&n,&s,&t);
    30     double L=0,R=0;
    31     for(int i=1;i<=n;i++) scanf("%d",&A[i]) , R=max(R,(double)A[i]);
    32     while(R-L>1e-4) {
    33         double M=L+(R-L)/2;
    34         if(can(M)) L=M;
    35         else R=M;
    36     }
    37     printf("%.3lf
    ",L);                                            
    38     return 0;
    39 }                  
  • 相关阅读:
    为什么puppeteer比selenium好?
    Puppeteer
    js跳出多层循环
    webpack loader- 图片处理
    webpack的loader的原理和实现
    Webpack中Loader的pitch方法
    url-loader和file-loader区别
    Vue中强制组件重新渲染的正确方法
    ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION :浏览器下载报错
    JSBridge的原理及使用
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4917391.html
Copyright © 2020-2023  润新知