题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2216

那个关于位置的代价是带根号的,所以随着距离的增加而增长变慢;所以靠后的位置一旦比靠前的位置优,就会一直更优(因为距离相同地增长,基数大的增长慢),所以有决策单调性。

一开始写了和 bzoj 4709 一样的实现,就是使得队列里相邻两个位置的 “后一个位置优于前一个位置的时间” 是单调递增的。但是却 TLE 。不知道为什么。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define db double
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
int g[];
void wrt(int x)
{
if(!x){puts("");return;}int t=;
while(x)g[++t]=x%,x/=;
for(int i=t;i;i--)putchar(g[i]+'');puts("");
}
int Mx(int a,int b){return a>b?a:b;}
const int N=5e5+;
int n,a[N],q[N],he,tl,ans[N];
db cal(int k,int bh){ return a[k]+sqrt((bh-k));}
int cz(int u,int v)
{
int l=u,r=n,ret=n+;
while(l<=r)
{
int mid=l+r>>;
if(cal(u,mid)>=cal(v,mid))ret=mid,r=mid-;
else l=mid+;
}
return ret;
}
int main()
{
n=rdn();
for(int i=;i<=n;i++)a[i]=rdn();
for(int i=;i<=n;i++)
{
while(tl-he>=&&cz(q[tl],q[tl-])>=cz(i,q[tl]))
tl--;
q[++tl]=i;
while(tl-he>=&&cz(q[he+],q[he+])<=i)he++;
ans[i]=ceil(cal(q[he+],i));
}
he=tl=; reverse(a+,a+n+);
for(int i=;i<=n;i++)
{
while(tl-he>=&&cz(q[tl],q[tl-])>=cz(i,q[tl]))
tl--;
q[++tl]=i;
while(tl-he>=&&cz(q[he+],q[he+])<=i)he++;
ans[n-i+]=Mx(ans[n-i+],ceil(cal(q[he+],i)));
}
//for(int i=1;i<=n;i++)printf("%d\n",Mx(0,ans[i]-a[n-i+1]));
for(int i=;i<=n;i++)wrt(ans[i]-a[n-i+]);
return ;
}

然后看题解,思路是维护每个决策点能转移给哪段区间。

把之前每个决策点控制的区间放进队列里,每次看看当前决策点 i 能把队尾的哪些区间弹掉(即自己覆盖那些区间,注意自己覆盖的区间应该在自己后面);先判断整个弹掉一个区间,就是看看在区间左端点是不是自己比那个决策点更优(左端点应该在 i 点后面);再在不能整个弹掉的时候判断 i 点能从区间的哪个位置开始往后控制,二分一下即可。

注意算代价应该用 double ,最后再 ceil 。因为过程中 ceil 的话,那个函数图象就不是很好,比如aaarticlea/png;base64,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" alt="" />,在二分的时候如果写了 <= 而不是 < ,又有一次 mid 取在了那个 3 和 4 重合的位置,就可能以为下面那个不优的图象在该位置后面是优于上面的。但即使写成 < 而不是 <= ,也还是会 WA , 一定要过程中用 double 才行。

注意把 i 作为决策点插入之后判断一下队首是不是 r > i ,因为插入的时侯可能改了队尾的 r ,即可能改了队首的 r ,所以要在插入之后判断。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define db double
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
db Mx(db a,db b){return a>b?a:b;}
const int N=5e5+;
int n,a[N],he,tl; bool fg; db ans[N];
struct Node{
int l,r,p;
Node(int l=,int r=,int p=):l(l),r(r),p(p) {}
}q[N];
db cal(int p,int k){ return a[p]+sqrt(k-p);}
void solve()
{
he=tl=;
for(int i=;i<=n;i++)
{
if(he==tl||cal(q[tl].p,n)<cal(i,n))
{
while(he<tl&&q[tl].l>=i&&cal(q[tl].p,q[tl].l)<=cal(i,q[tl].l))
tl--;//q[tl].l>=i
if(he<tl)
{
int l=Mx(i,q[tl].l),r=q[tl].r,ret=q[tl].r+;
//Mx(i,...) //q[tl].r+1
while(l<=r)
{
int mid=l+r>>;
if(cal(q[tl].p,mid)<cal(i,mid))ret=mid,r=mid-;
else l=mid+;
}
q[tl].r=ret-; if(ret<=n)q[++tl]=Node(ret,n,i);//if
}
else q[++tl]=Node(i,n,i);
}
while(he<tl&&q[he+].r<i)he++;//after!! for r change
ans[i]=Mx(ans[i],cal(q[he+].p,i));
}
}
int main()
{
n=rdn();
for(int i=;i<=n;i++)a[i]=rdn();
solve();
reverse(a+,a+n+); reverse(ans+,ans+n+); solve();//rev(ans)!
for(int i=n;i;i--)printf("%d\n",(int)ceil(ans[i])-a[i]);
return ;
}

bzoj 2216 [Poi2011]Lightning Conductor——单调队列+二分处理决策单调性的更多相关文章

  1. [bzoj 2216] [Poi2011] Lightning Conductor

    [bzoj 2216] [Poi2011] Lightning Conductor Description 已知一个长度为n的序列a1,a2,-,an. 对于每个1<=i<=n,找到最小的 ...

  2. bzoj 2216: [Poi2011]Lightning Conductor【决策单调性dp+分治】

    参考:https://blog.csdn.net/clove_unique/article/details/57405845 死活不过样例看了题解才发现要用double.... \[ a_j \leq ...

  3. bzoj 2216: Lightning Conductor 单调队列优化dp

    题目大意 已知一个长度为\(n\)的序列\(a_1,a_2,...,a_n\)对于每个\(1\leq i\leq n\),找到最小的非负整数\(p\)满足: 对于任意的\(j\), \(a_j \le ...

  4. 【BZOJ】2216: [Poi2011]Lightning Conductor

    题意 给一个长度为\(n\)的序列\(a_i\),对于每个\(1 \le i \le n\),找到最小的非负整数\(p\)满足 对于任意的\(j\), \(a_j \le a_i + p - \sqr ...

  5. bzoj 4709 [Jsoi2011]柠檬——单调栈二分处理决策单调性

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4709 题解:https://blog.csdn.net/neither_nor/articl ...

  6. 【BZOJ2216】[Poi2011]Lightning Conductor 决策单调性

    [BZOJ2216][Poi2011]Lightning Conductor Description 已知一个长度为n的序列a1,a2,...,an.对于每个1<=i<=n,找到最小的非负 ...

  7. P2698 [USACO12MAR]花盆Flowerpot(单调队列+二分)

    P2698 [USACO12MAR]花盆Flowerpot 一看标签........十分后悔 标签告诉你单调队列+二分了............ 每次二分花盆长度,蓝后开2个单调队列维护最大最小值 蓝 ...

  8. P3515 [POI2011]Lightning Conductor(决策单调性分治)

    P3515 [POI2011]Lightning Conductor 式子可转化为:$p>=a_j-a_i+sqrt(i-j) (j<i)$ $j>i$的情况,把上式翻转即可得到 下 ...

  9. 洛谷P3515 [POI2011]Lightning Conductor(动态规划,决策单调性,单调队列)

    洛谷题目传送门 疯狂%%%几个月前就秒了此题的Tyher巨佬 借着这题总结一下决策单调性优化DP吧.蒟蒻觉得用数形结合的思想能够轻松地理解它. 首先,题目要我们求所有的\(p_i\),那么把式子变一下 ...

随机推荐

  1. ChinaCock界面控件介绍-TCCImageViewerForm

    有多个图片,左右滑动可以切换,通过手势还可以放大.缩小查看,象常见的相册,就是这样子实现效果. 现在,我们有了TCCImageViewerForm组件,也可以轻松实现这样的场景应用. 现在看看TCCI ...

  2. IO-MYSQL的理解

    数据库IO简介   IO有四种类型:连续读,随机读,随机写和连续写,连续读写的IO size通常比较大(128KB-1MB),主要衡量吞吐量,而随机读写的IO size比较小(小于8KB),主要衡量I ...

  3. 【Think in java读书笔记】IO系统

    一.FIle类(处理文件目录问题) if else的另外一种写法 ,不加大括号也可以 import java.io.File; import java.io.FilenameFilter; impor ...

  4. tomcat多实例的端口设置

    需要改4个端口 8080  8009 8005 8443 8080改成8081 8005改成8105 8009改成8109 8443 改成8543

  5. 给Ubuntu软件升级命令

    以非root用户更新系统 sudo: sudo是linux系统管理指令,是允许系统管理员让普通用户执行一些或者全部的root命令的一个工具,如halt,reboot,su等等.这样不仅减少了root用 ...

  6. 20165228 实验一 Java开发环境的熟悉

    20165228 实验一 Java开发环境的熟悉 一.实验内容及步骤 (一)使用JDK编译.运行简单的Java程序 命令行下Java程序开发 1.用VrtualBox打开Linux虚拟机 2.使用Al ...

  7. 无重复字符的最长子串-LeetCode-第3题-C++

    题目:无重复字符的最长子串 题目描述:给定一个字符串,找出不含有重复字符的最长子串的长度. 最长不重复子串可能有很多个,但是其长度只有一种. 方法一:暴力搜索法 方法二:滑动窗口 哈希表:要查找一个元 ...

  8. 20155208徐子涵 2016-2017-2 《Java程序设计》第9周学习总结

    20155208徐子涵 2016-2017-2 <Java程序设计>第9周学习总结 教材学习内容总结 第十六章 整合数据库 16.1 JDBC入门 撰写应用程序是利用通信协议对数据库进行指 ...

  9. 关于js 异步回调的一些方法

    http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html

  10. 腾讯云JavaWeb环境配置

    腾讯云服务器Centos7系统配置javaWeb运行环境 java1.8 运行命令列表 yum list java-* 安装相应版本的jdk,一般含有devel的就是真正的jdk,如:java-1.8 ...