BZOJ - 2244 拦截导弹 (dp,CDQ分治+树状数组优化)
dp进阶之CDQ分治优化dp。
前置技能:dp基本功底,CDQ分治,树状数组。
问题等价于求二维最长上升子序列,是一个三维偏序问题(时间也算一维)。
设$dp[i]=(l,x)$为以第i枚导弹结尾的最优状态,$l$代表最长上升子序列长度,$x$代表长度为l的最长上升子序列数量,则$(l_0,x_0)$比$(l_1,x_1)$更优当且仅当$l_0>l_1$或($l_0=l_1$且$x_0>x_1$)。(实际上在转移的过程中,第二个条件没什么用)
根据题意有状态转移公式:$dp[i]=\left\{\begin{matrix}\begin{aligned}&(dp[j].l+1,dp[j].x),dp[j].l>dp[i].l\\ &(dp[j].l,dp[i].x+dp[j].x),dp[j].l=dp[i].l\end{aligned}\end{matrix}\right.$,要求$p[j].i<p[i].i,p[j].x<=p[i].x,p[j].y<=p[i].y$。
这样,最长上升子序列的长度就比较容易算了。可每枚导弹被选中的概率呢?等于导弹所在的最长上升子序列的数量/最长上升子序列的总数量,这就需要计算出每个导弹所在的最长上升子序列的个数。计算方法是对导弹正反各求一次dp数组,即分别算出以每枚导弹为起点和终点的最长上升子序列的长度l和数量x,每个导弹所在的最长上升子序列的个数就是两个x的乘积(如果两个l之和为最长上升子序列长度+1的话),否则为0。最长上升子序列的总数为所有导弹所在的最长上升子序列的个数之和/最长上升子序列长度。
由于数据量是5e4的,直接转移复杂度是$O(n^2)$的显然会超时。这时CDQ分治的作用就体现了,可以将复杂度优化到$O(nlog^2n)$。
首先把所有的导弹按照时间顺序排序(输入顺序就是),保证只发生从左边向右边的状态转移。
接下来就要保证x从小到大转移了。对x排序的话显然是会破坏时间顺序的,怎么办?将序列一分为二,对左右两部分的x值分别排序,只计算左半部分向右半部分的转移就行了。这个方法可以递归进行,执行的顺序为:解决左半部分的转移->计算从左半部分向右半部分的转移->解决右半部分的转移。
还剩下一维y怎么处理?再加个树状数组就行了。由于我们只关心y值的相对大小,而不关心它的绝对大小,所以可以离散化(注意下标要从1开始,为了使树状数组能够处理)。这个树状数组的更新过程和一般的树状数组的更新过程有所不同,更新的值是一个二元组(l,x),对l要取最值,对x要累加,即要同时发挥树状数组的维护区间最值和累加功能,并且要新增一个clr函数来撤销之前的更新操作(暴力memset太浪费时间)。
具体细节见代码实现。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=5e4+,inf=0x3f3f3f3f;
struct P {
int i,x,y;
bool operator<(const P& b)const {return x<b.x;}
} p[N],p2[N];
struct D {int l; db x;} c[N],dp[][N];
void upd(D& dp,D ad) {
if(dp.l<ad.l)dp.l=ad.l,dp.x=ad.x;
else if(dp.l==ad.l)dp.x+=ad.x;
}
int n,b[N],m;
int lowbit(int x) {return x&-x;}
void add(int u,D x) {for(; u<=m; u+=lowbit(u))upd(c[u],x);}
D get(int u) {D ret= {,}; for(; u; u-=lowbit(u))upd(ret,c[u]); return ret;}
void clr(int u) {for(; u<=m; u+=lowbit(u))c[u]= {,};}
db ans[N]; void CDQ(int l,int r,int f) {
if(l==r) {upd(dp[f][p[l].i], {,}); return;}
int mid=(l+r)>>;
CDQ(l,mid,f);
for(int i=l; i<=r; ++i)p2[i]=p[i];
sort(p2+l,p2+mid+),sort(p2+mid+,p2+r+);
int L,R;
for(R=mid+,L=l; R<=r; ++R) {
for(; L<=mid&&p2[L].x<=p2[R].x; ++L)add(p2[L].y, {dp[f][p2[L].i].l,dp[f][p2[L].i].x});
D t=get(p2[R].y);
upd(dp[f][p2[R].i], {t.l+,t.x});
}
for(int i=l; i<L; ++i)clr(p2[i].y);
CDQ(mid+,r,f);
} int main() {
scanf("%d",&n);
for(int i=; i<n; ++i)scanf("%d%d",&p[i].x,&p[i].y),p[i].i=i;
for(int i=; i<n; ++i)b[i]=p[i].y;
sort(b,b+n);
m=unique(b,b+n)-b;
memset(dp,,sizeof dp);
memset(c,,sizeof c);
for(int i=; i<n; ++i)p[i].x=-p[i].x,p[i].y=m-(lower_bound(b,b+m,p[i].y)-b);
CDQ(,n-,);
for(int i=; i<n; ++i)p[i].x=-p[i].x,p[i].y=m-p[i].y+;
reverse(p,p+n);
CDQ(,n-,);
D mx= {,};
for(int i=; i<n; ++i)upd(mx, {dp[][i].l+dp[][i].l-,dp[][i].x*dp[][i].x});
mx.x/=mx.l;
for(int i=; i<n; ++i)ans[i]=dp[][i].l+dp[][i].l-==mx.l?dp[][i].x*dp[][i].x/mx.x:;
printf("%d\n",mx.l);
for(int i=; i<n; ++i)printf("%f%c",ans[i]," \n"[i==n-]);
return ;
}
BZOJ - 2244 拦截导弹 (dp,CDQ分治+树状数组优化)的更多相关文章
- BZOJ2244 [SDOI2011]拦截导弹 【cdq分治 + 树状数组】
题目 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其 ...
- BZOJ 4553 [Tjoi2016&Heoi2016]序列 ——CDQ分治 树状数组
考虑答案的构成,发现是一个有限制条件的偏序问题. 然后三个维度的DP,可以排序.CDQ.树状数组各解决一维. #include <map> #include <cmath> # ...
- [BZOJ2244]:拦截导弹(DP+CDQ分治+树状数组)
题目传送门 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于 ...
- BZOJ 2683: 简单题(CDQ分治 + 树状数组)
BZOJ2683: 简单题(CDQ分治 + 树状数组) 题意: 你有一个\(N*N\)的棋盘,每个格子内有一个整数,初始时的时候全部为\(0\),现在需要维护两种操作: 命令 参数限制 内容 \(1\ ...
- BZOJ 1176 Mokia CDQ分治+树状数组
1176: [Balkan2007]Mokia Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 1854 Solved: 821[Submit][St ...
- BZOJ 2683 简单题 cdq分治+树状数组
题意:链接 **方法:**cdq分治+树状数组 解析: 首先对于这道题,看了范围之后.二维的数据结构是显然不能过的.于是我们可能会考虑把一维排序之后还有一位上数据结构什么的,然而cdq分治却可以非常好 ...
- 【bzoj2225】[Spoj 2371]Another Longest Increasing CDQ分治+树状数组
题目描述 给定N个数对(xi, yi),求最长上升子序列的长度.上升序列定义为{(xi, yi)}满足对i<j有xi<xj且yi<yj. 样例输入 8 1 3 3 2 1 1 4 5 ...
- 【BZOJ4553】[Tjoi2016&Heoi2016]序列 cdq分治+树状数组
[BZOJ4553][Tjoi2016&Heoi2016]序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能 ...
- 【bzoj3262】陌上花开 CDQ分治+树状数组
题目描述 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa&g ...
随机推荐
- ionic项目注意点
1.controller 名字一定要大写 config如过传递controller,则要使用controllerAs ,开头使用小写 2.在scss中新添加scss文件,要重启
- 【转】通过fio工具,测试SATA,SAS,SSD 读写性能
转自:http://blog.csdn.net/killmice/article/details/42745937
- ORA-28002 the password will expire
ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;
- 20145240 《Java程序设计》第六周学习总结
20145240 <Java程序设计>第六周学习总结 教材学习内容总结 InputStream与OutputStream 10.1.1串流设计的概念 Java将输入/输出抽象化为串流,数据 ...
- iptables DNAT、SNAT和MASQUERATE
MASQUERADE 地址伪装,和SNAT功能一样,只不过SNAT使用固定IP地址,MASQUERADE使用网卡上的地址. SNAT配置: iptables -t nat -A POSTROUTING ...
- ios开发在导入环信SDK后运行出现 Reason: image not found 的解决方案
在导入环信的SDK后,运行出现:
- oracle 导出
一.导出csv文件 利用Oracle中的Spool缓冲池技术可以实现Oracle数据导出到文本文件. 1).在Oracle PL/SQL中输入缓冲开始命令,并指定输出的文件名: spool /tmp/ ...
- JavaScript实现的功能
1.js事件阻止冒泡的应用 1)问题描述: 单机除了这两个元素,触发事件,: 可用阻止事件冒泡 2)解决方法: $('body').click(function(e){ $('#searchTree' ...
- DataX的安装
DataX的安装 1. 可下载tar包 https://github.com/alibaba/DataX/blob/master/userGuid.md 2. 下载源码自己编译 git clone h ...
- 防域名DNS劫持 从保护帐号安全做起
什么攻击能造成区域性的网络瘫痪?没错,DNS劫持.这个堪称核武器的攻击方式,一旦爆炸,后果不堪设想.2014年1月21日,全国大范围出现DNS故障,下午,中国顶级域名根服务器出现故障,大部分网站受影响 ...