分析

题目要求求一个最大的实数\(x\),使得某长度在\([S,T]\)之间的区间\([L,R]\)满足

\[\frac{\sum_{i=L}^{R}a_i}{R-L+1}=x
\]

\[\sum_{i=L}^{R}a_i=x*(R-L+1)
\]

由于答案满足单调性,所以可以二分\(x\),转化为判断问题,即判断

\[\sum_{i=L}^{R}a_i\geq x*(R-L+1)
\]

\(\rightarrow\)

\[\sum_{i=L}^{R}\left(a_i-x \right)\geq0
\]

对这个式子求前缀和,就可快速算出一段区间的和,令

\[sum_i=\sum_{i=1}^{i}\left(a_i-x \right)
\]

则区间\([L,R]\)合法的条件为

\[sum_R-sum_{L-1}\geq0
\]

转化成这种形式,已经很好做了。维护一个单增的单调队列,然后判断当前遍历元素是否大于等于队首元素即可。

时间复杂度

假设数据范围为\(A\),则二分答案是\(O(\log A)\)的,判断一次用了前缀和和单调队列,是\(O(n)\)的,总时间复杂度为\(O(n\log A)\)。

小优化

题目要求保留3位小数,而对浮点数的操作很麻烦,所以不妨对每个数乘10000(多一位是因为要四舍五入),然后算答案时再除10000.0就行了。


用STL的deque实现单调队列,嫌慢手打,使用相同API即可~~(然而这题不卡可以水^_^)~~。

#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);
}

Hint

最后说一下单调队列的边界问题。合法区间\([L,R]\)满足

\[S\leq R-L+1\leq T
\]

由于使用前缀和,那么\(i\),\(p\)应满足

\[S+1\leq i-p+1\leq T+1
\]

也就是说应弹掉\(p<i-T\)的那些点。

还有就是二分答案的边界。求最后一个类型应该int M=(L+R+1)>>1;

LG1419 【寻找段落】的更多相关文章

  1. LuoguP1419 寻找段落(二分 单调队列

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

  2. P1419 寻找段落

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

  3. 洛谷—— P1419 寻找段落

    https://www.luogu.org/problem/show?pid=1419 题目描述 给定一个长度为n的序列a_i,定义a[i]为第i个元素的价值.现在需要找出序列中最有价值的“段落”.段 ...

  4. [洛谷P1419] 寻找段落

    一道单调队列的好题 传送门:>Here< 题意:求一个连续子段,其长度在\([S,T]\)之间,使其平均值最大.保留三位小数 解题思路 考虑二分答案,转化为判定问题.设当前二分到\(k\) ...

  5. 【洛谷 P1419】 寻找段落(二分答案,单调队列)

    题目链接 开始还以为是尺取.发现行不通. 一看标签二分答案,恍然大悟. 二分一个\(mid\)(实数),把数列里每个数减去\(mid\),然后求前缀和,在用单调队列维护\(sum[i-t\text{~ ...

  6. 【Luogu】P1419寻找段落(单调队列)

    题目链接 不知为何状态突然奇差无比,按说这题本来应该是水题的,但不仅不会做,还比着题解爆零五次 二分平均值(想到了),单调队列维护最大区间和(想到了但是不会,???为什么我不会???) #includ ...

  7. luoguP1419 寻找段落(二分答案+单调队列)

    题意 给定一个长度为n的序列a1~an,从中选取一段长度在s到t之间的连续一段使其平均值最大.(n<=100000) 题解 二分答案平均值. judge时把每一个a[i]-mid得到b[i] 在 ...

  8. 洛谷P1419寻找段落

    题目 单调队列+前缀和 #include <bits/stdc++.h> #define N 101001 using namespace std; int n, s, t; int da ...

  9. luogu1419 寻找段落 (二分,单调队列)

    单调队列存坐标 #include <iostream> #include <cstdio> #include <cstring> #include <algo ...

随机推荐

  1. R语言-attach、detach、with

    在R语言中,对于串列,数据框中的数据的进行操作时,为了避免重复地键入对象名称,可使用attach或with. 1.attach() 假设data.frame包含列name,age attach(one ...

  2. Python版本微信跳一跳,软件配置

    一.安装python3的环境: 直接从python官方网站下载python3的安装包,直接安装. 记得将python3放到PATH环境变量中,安装的过程中在该配置地方打钩就可以了. 如果安装的过程中出 ...

  3. 使用 Python 的 Socket 模块构建一个 UDP 扫描工具

    译文:oschina 英文:bt3gl 当涉及到对一些目标网络的侦察时,出发点无疑是首先发现宿主主机.这个任务还可能包含嗅探和解析网络中数据包的能力. 几周前,我曾经谈到了如何使用Wireshark来 ...

  4. mysql 随机获取数据并插入到数据库中

    insert into result (user_id, activity_id, number) select user_id, activity_id from `activity_record` ...

  5. ccf数字排序

    问题描述 给定n个整数,请统计出每个整数出现的次数,按出现次数从多到少的顺序输出. 输入格式 输入的第一行包含一个整数n,表示给定数字的个数. 第二行包含n个整数,相邻的整数之间用一个空格分隔,表示所 ...

  6. java.lang.string split 以点分割字符串无法正常拆分字符串

    //错误的做法String ip="192.168.11.23"; String[] spstr_IP=ip.split(".");//这种方式无法拆分在ip字 ...

  7. 隔离级别 && SNAPSHOT

    read uncommitted | 0 未提交读 将查询的隔离级别指定为 0. 可以读脏数据. 读脏数据:一事务对数据进行了增删改,但未提交,有可能回滚,另一事务却读取了未提交的数据.   例: 公 ...

  8. OC 方法和函数

    /* 方法 1.对象方法都是以减号 - 2.对象方法的声明必须写在@interface和@end之间 对象方法的实现必须写在@implementation和@end之间 3.对象方法只能由对象来调用 ...

  9. RpcContext

    RpcContext内部有一个ThreadLocal变量,它是作为ThreadLocalMap的key,表明每个线程有一个RpcContext. public class RpcContext { p ...

  10. popen strtok 函数的使用

    FILE * popen ( const char * command , const char * type ); int pclose ( FILE * stream );   type 参数只能 ...