poj2018 Best Cow Fences[二分答案or凸包优化]
首先暴力很好搞,但是优化的话就不会了。放弃QWQ。
做法1:二分答案
然后发现平均值是$ave=\frac{sum}{len}$,这种形式似乎可以二分答案?把$len$移到左边。
于是二分$ave$,去找数列有没有区间和大于等于其$len$乘以$ave$的,然后卡住了。。
有一个很巧的转化,把每个数都减去一个$ave$,然后任意区间和就相当于把$ave$累加了$len$次。
于是乎只要看区间和$S-len*ave$是否大于等于0就可以了。
存在这样一个区间就说明$ave$可以更大,否则要小。查找存在性是一个简单的前缀和dp。
$O(nlogn)$。
poj精度死活卡不过去。
看来技巧还不够。
于是一气之下把所有double型全换成long long,也就是把小数点后五位通通看成整数,然后运算,最后除以100。
唉。
启示:关于平均数的题目很多时候都是用二分答案处理的。因为是分数形式。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define dbg(x) cerr << #x << " = " << x <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=1e5+;
const db eps=1e-;
ll A[N],s[N];
ll L=,R,mid;
int n,l;
inline bool check(ll ave){
for(register int i=;i<l;++i)s[i]=s[i-]+A[i]-ave;
ll minx=1e16;
for(register int i=l;i<=n;++i){
MIN(minx,s[i-l]);s[i]=s[i-]+A[i]-ave;
if(s[i]-minx>=)return ;
}
return ;
} int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
read(n),read(l);
for(register int i=;i<=n;++i)A[i]=read(A[i])*,MAX(R,A[i]);
while(L<R){
mid=L+R+>>;
if(check(mid))L=mid;
else R=mid-;
}
printf("%lld",(L/));
return ;
}
做法2:凸包优化
发现以每个点结尾的平均值$ave_i=\frac{S_i-S_j}{i-j}$ $0 \leq j \leq m$
于是想到斜率。问题变成:在前面的区间内找一点与$i$号点连线斜率最大。
然后发现上凸的3个点,中间那个没有用,所以维护一个下凸包。
查找的话是需要二分的,二分找下凸包里斜率$k_{i-1}<k_{i}>k_{i+1}$的这个点。
但是,基于这题并不是让求每个点结尾的最大平均数,而是全局的。
所以有这么一个神仙思路优化复杂度:
在查找时不要二分了,从队首开始比较,若$k_{l,i}<k_{l+1,i}$则弹出队首。
一直到找到这个最大斜率点,作为这个$i$的局部答案。
如果之后出现一个点,他和之前弹出过的点的斜率比目前没有弹出的点间的斜率都要大呢?
是有这种情况的。

但是,他不会影响全局最优解的形成,即使对于以$i$结尾算错了也没关系。
为什么呢。观察上面这种情况,在1点把下凸包前面一堆全弹掉了。发生这种情况当且仅当这个1号点在橙色线上方。
而2号点那种斜率最大的出现在已经弹出了的点里,必须满足在橙色线下方。
一旦有弹出,那么1号点决策一定比2号点的优。所以2号点算错了也不影响全局最大值。
所以这样的做法是$O(n)$获取全局最优解的。
所以网上说的都是并不严谨的。
这个$O(n)$做法正确性的证明是由hkk神仙提出来的,感谢!大家觉得好可以多去膜他。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define dbg(x) cerr << #x << " = " << x <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=1e5+;
db ans;
int n,m;
int S[N],q[N],l=,r; int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
read(n),read(m);
for(register int i=;i<=n;++i)S[i]=S[i-]+read(S[i]);
for(register int i=m;i<=n;++i){
while(l<r&&(S[i-m]-S[q[r]])*1ll*(q[r]-q[r-])<=(S[q[r]]-S[q[r-]])*1ll*(i-m-q[r]))--r;
q[++r]=i-m;
while(l<r&&(S[i]-S[q[l]])*1ll*(i-q[l+])<=(S[i]-S[q[l+]])*1ll*(i-q[l]))++l;
MAX(ans,(db)(S[i]-S[q[l]])/(db)(i-q[l]));
}
printf("%d\n",(int)(ans*));
return ;
}
poj2018 Best Cow Fences[二分答案or凸包优化]的更多相关文章
- POJ-2018 Best Cow Fences(二分加DP)
Best Cow Fences Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 10174 Accepted: 3294 Desc ...
- loj#10012\poj2018 Best Cow Fences(二分)
题目 #10012 「一本通 1.2 例 2」Best Cow Fences 解析 有序列\(\{a_i\}\),设\([l,r]\)上的平均值为\(\bar{x}\),有\(\sum_{i=l}^r ...
- POJ-2018 Best Cow Fences 二分
题意:找到一个连续区间,区间的长度至少大于f,现在要求这个区间的平均值最大. 题解: 二分找答案. 每次对于2分的mid值, 都把原来的区间减去mid, 然后找到一长度至少为f的区间, 他们的区间和& ...
- POJ2018 Best Cow Fences 二分
实数折磨人啊啊啊啊啊啊啊 好,实数应该是最反人类的东西了...... 这个害得我调了0.5天才过. 大意是这样的:给你一个数列,求其中不少于f个的连续数的最大平均值. 不禁想起寒假的课程来... 此处 ...
- POJ2018 Best Cow Fences —— 斜率优化DP
题目链接:https://vjudge.net/problem/POJ-2018 Best Cow Fences Time Limit: 1000MS Memory Limit: 30000K T ...
- bzoj 2402: 陶陶的难题II 二分答案维护凸包
2402: 陶陶的难题II Time Limit: 40 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 68 Solved: 45[Submi ...
- Poj2018 Best Cow Fences
传送门 题目大意就是给定一个长度为 n 的正整数序列 A ,求一个平均数最大的,长度不小于 L 的子序列. 思路: 二分答案. Code: #include<iostream> #incl ...
- poj2018——Best Cow Fences
Description Farmer John's farm consists of a long row of N (1 <= N <= 100,000)fields. Each fie ...
- Poj 2018 Best Cow Fences(分数规划+DP&&斜率优化)
Best Cow Fences Time Limit: 1000MS Memory Limit: 30000K Description Farmer John's farm consists of a ...
随机推荐
- OpenCV阈值化处理
图像的阈值化就是利用图像像素点分布规律,设定阈值进行像素点分割,进而得到图像的二值图像.图像阈值化操作有多种方法,常用方法有经典的OTSU.固定阈值.自适应阈值.双阈值及半阈值化操作.这里对各种阈值化 ...
- HCL试验5
PC端配置:配置ip地址 交换机1配置:①创建VLAN system-view vlan 10 vlan 20 ②配置PC端接口 interface gi 1/0/1 port link-type a ...
- Centos 安装k8s 集群(单master开发环境)
本教程是在VM中搭建K8s 所以第一步骤先配置虚拟机的ip 和上网情况详细参考https://www.cnblogs.com/chongyao/p/9209527.html 开始搭建K8s集群 两台机 ...
- PreparedStatement 以及事务的注意事项
a).PreparedStatement 可以进行批量操作,但是与Statement有一定的区别 1. Statement可以进行不同sql语句的批量操作 即可以同时进行 crud 操作. Strin ...
- python-day9(正式学习)
目录 深浅拷贝 拷贝 浅拷贝 深拷贝 异常处理 什么是异常 语法错误 逻辑错误 异常的种类 常用的异常 其他异常 异常处理 提前预防 事后预防 抛出异常(基本没用) 断言(调试用,现在基本上没用) 文 ...
- 加快ALTER TABLE 操作速度
mysql的alter table操作的性能对于大表来说是个大问题.mysql大部分修改表结构操作的方法都是用新的结构创建一个 新表,从旧表中查出数据插入新表,然后在删除旧表.这样的操作很耗费时间,而 ...
- leetcode中等题
# Title Solution Acceptance Difficulty Frequency 1 Two Sum 44.5% Easy 2 Add Two Number ...
- zookeeperAPI的常用方法
zookeeper支持三种部署方式: 1 单机 2 集群 3 伪集群 删除节点 zkClient.delete(path);
- MySQL性能优化(一):优化方式
原文:MySQL性能优化(一):优化方式 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/v ...
- C# 面向对象1(类和对象的概念)
1.面向过程-->面向对象 面向过程:面向的是完成这件事儿的过程,强调的是完成这件事儿的动作. 2.面向过程的思想: 以上的,需求一更改,会导致不同的方法,一一去更改. 3.面向对象的思想:找个 ...