bzoj 2216 [Poi2011]Lightning Conductor——单调队列+二分处理决策单调性
题目: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——单调队列+二分处理决策单调性的更多相关文章
- [bzoj 2216] [Poi2011] Lightning Conductor
[bzoj 2216] [Poi2011] Lightning Conductor Description 已知一个长度为n的序列a1,a2,-,an. 对于每个1<=i<=n,找到最小的 ...
- bzoj 2216: [Poi2011]Lightning Conductor【决策单调性dp+分治】
参考:https://blog.csdn.net/clove_unique/article/details/57405845 死活不过样例看了题解才发现要用double.... \[ a_j \leq ...
- bzoj 2216: Lightning Conductor 单调队列优化dp
题目大意 已知一个长度为\(n\)的序列\(a_1,a_2,...,a_n\)对于每个\(1\leq i\leq n\),找到最小的非负整数\(p\)满足: 对于任意的\(j\), \(a_j \le ...
- 【BZOJ】2216: [Poi2011]Lightning Conductor
题意 给一个长度为\(n\)的序列\(a_i\),对于每个\(1 \le i \le n\),找到最小的非负整数\(p\)满足 对于任意的\(j\), \(a_j \le a_i + p - \sqr ...
- bzoj 4709 [Jsoi2011]柠檬——单调栈二分处理决策单调性
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4709 题解:https://blog.csdn.net/neither_nor/articl ...
- 【BZOJ2216】[Poi2011]Lightning Conductor 决策单调性
[BZOJ2216][Poi2011]Lightning Conductor Description 已知一个长度为n的序列a1,a2,...,an.对于每个1<=i<=n,找到最小的非负 ...
- P2698 [USACO12MAR]花盆Flowerpot(单调队列+二分)
P2698 [USACO12MAR]花盆Flowerpot 一看标签........十分后悔 标签告诉你单调队列+二分了............ 每次二分花盆长度,蓝后开2个单调队列维护最大最小值 蓝 ...
- P3515 [POI2011]Lightning Conductor(决策单调性分治)
P3515 [POI2011]Lightning Conductor 式子可转化为:$p>=a_j-a_i+sqrt(i-j) (j<i)$ $j>i$的情况,把上式翻转即可得到 下 ...
- 洛谷P3515 [POI2011]Lightning Conductor(动态规划,决策单调性,单调队列)
洛谷题目传送门 疯狂%%%几个月前就秒了此题的Tyher巨佬 借着这题总结一下决策单调性优化DP吧.蒟蒻觉得用数形结合的思想能够轻松地理解它. 首先,题目要我们求所有的\(p_i\),那么把式子变一下 ...
随机推荐
- C++中数组定义及初始化
一.一维数组 静态 int array[100]; 定义了数组array,并未对数组进行初始化 静态 int array[100] = {1,2}: 定义并初始化了数组array 动态 int* ar ...
- svn+http+ad域
svn本地添加用户太麻烦了,如果公司有一百个开发人员要访问,要创建账号密码太麻烦了:所以让他们用AD域账号去登录就很方便,但是权限的管控还是在svn的本地添加(这个暂时还没办法很好的解决) 一.安装依 ...
- DOM树中节点与节点之间的关系图
获取子代元素节点:children 获取所有子代元素节点数:**.childElementCount 或者 **.children.length
- Spring 消息
RMI.Hessian/Burlap的远程调用机制是同步的.当客户端调用远程方法时,客户端必须等到远程方法完成之后,才能继续执行.即使远程方法不向客户端返回任何消息,客户端也要被阻塞知道服务完成. 消 ...
- [转] Haproxy、Keepalived双主高可用负载均衡
http://blog.chinaunix.net/uid-25266990-id-3989321.html 在测试了Nginx+Keepalived的负载均衡后,也对Haproxy+Keepaliv ...
- java通过配置文件(Properties类)连接Oracle数据库代码示例
import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java. ...
- Selenium之ActionChains(一)
今天,分享的是ActionChains的使用方法. 先来说一下今天要用到的方法: click(element=null) 点击元素,参数 ...
- python发送HTTP POST请求
1. 127.0.0.1和0.0.0.0 127.0.0.1是一个回送地址,指本地机,一般用来本机测试使用,使用127.0.0.1启的服务只能在本地机器上访问,使用0.0.0.0启的服务可以在其他机器 ...
- Learning to Rank Short Text Pairs with Convolutional Deep Neural Networks(paper)
本文重点: 和一般形式的文本处理方式一样,并没有特别大的差异,文章的重点在于提出了一个相似度矩阵 计算过程介绍: query和document中的首先通过word embedding处理后获得对应的表 ...
- 20155208 2006-2007-2 《Java程序设计》第1周学习总结
20155208徐子涵 2016-2017-2 <Java程序设计>第1周学习总结 教材学习内容总结 浏览教材 每章提出自己存在的问题 chapter1:JDK和JRE的区别体现在什么地方 ...