题目: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. Android UIAutomator 定位

    AndroidUIAutomator:Android的源生测试框架的定位方式,定位速度快 一.组合定位 1.一般组合用id,class,text这三个属性会比较好一点,但也可以组合定位 2.id与te ...

  2. ​插件化DPI在商用WIFI中的价值

    插件化DPI是指DPI(深度包检测)技术以插件/模块的方式嵌入到各种网络设备中,是一种新型轻量级资源消耗的互联网技术,由迈科网络(股份代码:430575)独创开发. 插件化DPI(深度包检测)技术服务 ...

  3. Python基础3--Python复杂数据类型

    1 堆 堆是一种二叉树,其中每个父节点的值都小于或等于其所有子节点的值,最小的元素总是位于二叉树的根节点. 堆的创建 import heapq import random data = range(1 ...

  4. 日期和API

    Java1.0对日期和时间的支持只能依赖java.util.Date类,年份的起始选择是1900你那,月份的起始是从0开始计算的.它的返回值中包含了JVM的默认市区CET,即中欧时间.在Java1.1 ...

  5. Git的小总结

    1.Git的介绍 Git(分布式版本控制系统)是一款免费.开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. 下载地址:https://git-scm.com 2.介绍命令 $ git ...

  6. H5之localStorage,sessionStorage

    在以前的时候也听说过一些h5缓存技术,具体也没有去使用过,就在前两三个礼拜我用了localStorage和sessionStorage这两个存储方式, 我使用这些存储技术,也是想减少访问服务器的请求, ...

  7. [LeetCode&Python] Problem 905: Sort Array By Parity

    Given an array A of non-negative integers, return an array consisting of all the even elements of A, ...

  8. AE1

    i2.1 导入四种方式: 1.文件->导入 2.项目窗口空白区域双击 3.空白区域右键 4 ctrl+i 常用键: ctri+i    ctrl shift  alt delete 2.2移动属 ...

  9. unet网络讲解,附代码

    转: http://www.cnblogs.com/gujianhan/p/6030639.html key1: FCN对图像进行像素级的分类,从而解决了语义级别的图像分割(semantic segm ...

  10. libsvm使用总结

    ./tools/ subset.py  分割数据集 grid.py   优化参数c.g checkdata.py   检测数据集格式 easy.py   综合 ./windows/ svm-scale ...