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\),那么把式子变一下 ...
随机推荐
- xampp 忘记密码的处理方式.
网上看到一些方法: 大部分是第一种: 方法一 这个方法, 我使用的时候没有生效. -------------- 后来看到另外一种方法 . 直接替换user表的三个文件. 这个方法成功了. xam ...
- ChinaCock界面控件介绍-CCNewsSilder
上图是控件包里的Demo运行效果,轮播新闻图片. 这个控件用起来简单,拖放一个CCNewsSiler到Form上,设置Align为Top,再设置好高度,然后用代码加载图片: procedure TFo ...
- python selenium爬取QQ空间方法
from selenium import webdriver import time # 打开浏览器 dr = webdriver.Chrome() # 打开某个网址 dr.get('https:// ...
- 【Python】爬虫-1
#练习1:获取搜狐网页上所有的URL并且把与篮球有关的内容筛选出来 #算法: #.获取搜狐网站所有内容 #.判断哪些是链接,获取URL格式有效的链接 #.获取每个有效URL网页的内容 #.判断内容是否 ...
- Springmvc+WebSocket整合
WebSocket是为解决客户端与服务端实时通信而产生的技术.其本质是先通过HTTP/HTTPS协议进行握手后创建一个用于交换数据的TCP连接,此后服务端与客户端通过此TCP连接进行实时通信. 以前我 ...
- POJ2785-4 Values whose Sum is 0
传送门:http://poj.org/problem?id=2785 Description The SUM problem can be formulated as follows: given f ...
- Oracle表的查询(一)
表查询关键字.字段.表名不加引号时不区分大小写引号定义的内容区分大小写运算中有null值时,结果为null*nvl(字段,赋值):如果字段值为null,则取后面一个值*like 关键字:%表示若干个字 ...
- requestAnimationFrame结束demo
- TensorRT caffemodel serialize
1.TensorRT的需要的文件 需要的基本文件(不是必须的) 1>网络结构文件(deploy.prototxt) 2>训练的权重模型(net.caffemodel) TensorRT 2 ...
- Python之路,第十二篇:Python入门与基础12
python3 函数3 装饰器 decorator *** 概念:装饰器是一个函数,主要作用是用来包装另一个函数或类: 包装的目的:是在不改变原函数名的情况下,改变被包装函数(对象)的行为. 装饰 ...