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\),那么把式子变一下 ...
随机推荐
- 位(bit)、字节(Byte)、MB(兆位)之间的换算关系
B是Byte的缩写,意思是字节:b是bit的缩写,意思是比特位:Kb是千比特位,KB是千字节:MB意思是兆字节: 换算关系: 1MB=1024KB=1024B*1024=1048576B: 8bit= ...
- php usort
<?phpfunction re($a,$b){ return ($a>$b)?1:-1; }$x=array(1,3,2,5,9);usort($x, 're');print_r($x) ...
- winform datatable 或datagridview中添加列
DataGridViewCheckBoxColumn dg = new DataGridViewCheckBoxColumn(); dg.HeaderText = "选择"; dg ...
- 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6152 Friend-Graph(暴力搜索)
题目传送:http://acm.hdu.edu.cn/showproblem.php?pid=6152 Problem Description It is well known that small ...
- Threejs着色器基本使用样例改造
<!DOCTYPE html> <html lang="en"> <head> <title>three.js webgl - bu ...
- 【重要】NOI-1.2-10-字符串大小
10:Hello, World!的大小 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 还记得在上一章里,我们曾经输出过的“Hello, World!”吗? ...
- C++中输出字符到文本文档
#include <iostream> #include <fstream> //ofstream类的头文件 using namespace std; int main() { ...
- 新添加一块硬盘制作LVM卷并进行分区挂载
linux服务器新添加一块硬盘,可以直接将盘格式化挂载就能用,比如挂载在/usr/local目录,但是这样有一个弊端,就是如果这一块磁盘满了,后续想要扩容的话,不能继续挂载这个/usr/local挂载 ...
- Gym - 101002D:Programming Team (01分数规划+树上依赖背包)
题意:给定一棵大小为N的点权树(si,pi),现在让你选敲好K个点,需要满足如果如果u被选了,那么fa[u]一定被选,现在要求他们的平均值(pi之和/si之和)最大. 思路:均值最大,显然需要01分数 ...
- IE8的兼容问题
1: rgba失效的问题: 在添加rgba的类名内加上:filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#7f00000 ...