博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj4476: [Jsoi2015]送礼物
阅读量:4980 次
发布时间:2019-06-12

本文共 2499 字,大约阅读时间需要 8 分钟。

考虑二分答案

对于一个区间一定是一边最大一边最小是最优的,还有不够补足L的情况,这个RMQ就好

枚举右端点是最大/最小,单调队列搞搞就完了

#include
#include
#include
#include
#include
#include
using namespace std;const int _=1e2;const int maxn=5e4+_;const int mbit=30;int n,K,L,R,a[maxn];namespace ST{ int Bin[mbit],Log[maxn],mx[mbit][maxn],mn[mbit][maxn]; void main() { Bin[0]=1;for(int i=1;i<=25;i++)Bin[i]=Bin[i-1]*2; Log[1]=0;for(int i=2;i<=n ;i++)Log[i]=Log[i/2]+1; for(int i=1;i<=n;i++)mx[0][i]=mn[0][i]=a[i]; for(int j=1;Bin[j]<=n;j++) for(int i=1;i+Bin[j]-1<=n;i++) mx[j][i]=max(mx[j-1][i],mx[j-1][i+Bin[j-1]]), mn[j][i]=min(mn[j-1][i],mn[j-1][i+Bin[j-1]]); } int mxRMQ(int x,int y) { int k=Log[y-x+1]; return max(mx[k][x],mx[k][y-Bin[k]+1]); } int mnRMQ(int x,int y) { int k=Log[y-x+1]; return min(mn[k][x],mn[k][y-Bin[k]+1]); } double stu1() { double ans=0; for(int j=L;j<=n;j++) { ans=max(ans,(double)(mxRMQ(j-L+1,j)-mnRMQ(j-L+1,j))/(L-1+K)); } return ans; }}namespace DD{ double em; namespace A { struct mnlist//单调减 { int head,tail,pos[maxn]; void clear(){head=1,tail=0;} void push_back(int x) { while(head<=tail&&(double)-a[pos[tail]]<=(double)-a[x]+em*(x-pos[tail]))tail--; pos[++tail]=x; } void pop_top(int lim){ while(head<=tail&&pos[head]<=lim)head++;} int top(){ return pos[head];} }A; bool check() { A.clear(); for(int j=L;j<=n;j++) { A.pop_top(j-R);//<=该决策点无效 A.push_back(j-L+1); int i=A.top(); if((double)(a[j]-a[i])+em*i>=em*(K+j))return true; } return false; } } //~~~~~~~~~~~~~~A~~~~~~~~~~~~~~~~~~~~ namespace B { struct mxlist { int head,tail,pos[maxn]; void clear(){head=1,tail=0;} void push_back(int x) { while(head<=tail&&(double)a[pos[tail]]<=(double)a[x]+em*(x-pos[tail]))tail--; pos[++tail]=x; } void pop_top(int lim){ while(head<=tail&&pos[head]<=lim)head++;} int top(){ return pos[head];} }B; bool check() { B.clear(); for(int j=L;j<=n;j++) { B.pop_top(j-R);//<=该决策点无效 B.push_back(j-L+1); int i=B.top(); if((double)(a[i]-a[j])+em*i>=em*(K+j))return true; } return false; } } //~~~~~~~~~~~~~~B~~~~~~~~~~~~~~~~~~~~ bool check(){ return A::check()|B::check();} double stu2() { double el=0,er=1e8; while(er-el>1e-5) { em=(el+er)/2; if(check())el=em; else er=em; } return el; }}int main(){ int T; scanf("%d",&T); while(T--) { scanf("%d%d%d%d",&n,&K,&L,&R); for(int i=1;i<=n;i++)scanf("%d",&a[i]); ST::main(); printf("%.4lf\n",max(ST::stu1(),DD::stu2())); } return 0;}

 

转载于:https://www.cnblogs.com/AKCqhzdy/p/10603886.html

你可能感兴趣的文章
ExtJs4 笔记 Ext.Panel 面板控件、 Ext.window.Window 窗口控件、 Ext.container.Viewport 布局控件...
查看>>
Django框架—ORM操作笔记
查看>>
FireDAC如何连接ORACLE数据库
查看>>
(转)logback配置详解
查看>>
解决电脑系统卡、慢 3分钟成为高手!
查看>>
9. Palindrome Number
查看>>
52. N-Queens II
查看>>
ORA-01555错误总结(二)
查看>>
flask简单demo
查看>>
SSH
查看>>
卷积神经网络—第一周
查看>>
如何形容这份美?
查看>>
linux 新增硬盘分区格式化
查看>>
暴零狗的泉五之旅 8-21
查看>>
【bzoj2431】[HAOI2009]逆序对数列 dp
查看>>
7 天玩转 ASP.NET MVC — 第 6 天
查看>>
论互联网合并趋势之不一样的「合并」
查看>>
JAVA 反序列化攻击
查看>>
CF1153F Serval and Bonus Problem 【期望】
查看>>
HTML5+CSS4基础知识测试
查看>>