[BZOJ2244][SDOI2011]拦截导弹 CDQ分治
2244: [SDOI2011]拦截导弹
Time Limit: 30 Sec Memory Limit: 512 MB Special Judge
Description
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度、并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其拦截的导弹的飞行速度也不能大于前一发。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
在不能拦截所有的导弹的情况下,我们当然要选择使国家损失最小、也就是拦截导弹的数量最多的方案。但是拦截导弹数量的最多的方案有可能有多个,如果有多个最优方案,那么我们会随机选取一个作为最终的拦截导弹行动蓝图。
我方间谍已经获取了所有敌军导弹的高度和速度,你的任务是计算出在执行上述决策时,每枚导弹被拦截掉的概率。
Input
第一行包含一个正整数n,表示敌军导弹数量;
下面 行按顺序给出了敌军所有导弹信息:
第i+1行包含2个正整数hi和vi,分别表示第 枚导弹的高度和速度。
Output
输出包含两行。
第一行为一个正整数,表示最多能拦截掉的导弹数量;
第二行包含n个0到1之间的实数,第i个数字表示第i枚导弹被拦截掉的概率(你可以保留任意多位有效数字)。
Sample Input
Sample Output
对于100%的数据,1≤n≤5*104, 1≤hi ,vi≤109;
均匀分布着约50%的数据,满足1≤hi ,vi≤1000。
题解:
我们分析一下这道题,其实他分为两个子任务,
一个是计算最长的三维偏序的不下降子序列,
一个是计算每枚导弹在所有可能的方案中出现了多少次.
首先我们离散一下,方便处理.
接着我们考虑,对于导弹i,他处在的导弹序列首先他自己一定在里面,其次序列一定是前面一段后面一段(废话.....)
这样总的方案数就应该是前面一段的方案数*后面一段的方案数.
那么我们考虑类似最短路计数问题的处理方法,我们处理一个类似的f数组,f[0]表示以i开始/f[1]表示以i结束的最长子序列长度
同时统计一个g数组,g[0]表示以i开始/g[0]表示以i结束的最长子序列方案数,在CDQ转移的时候如果长度相等累加,长度不等就覆盖上去
这两个数组正反两遍CDQ就可以计算得到
这样,按照上面的计算方式,总的方案数就应该是g[0][i]*g[1][i].
那么如果某个导弹处在最长子序列中,一定会有f[0][i]+f[1][i]-1==maxlength(-1是因为要把自己减去,不能算两遍)
设总方案数为sum,那么这枚导弹出现的概率就是g[0][i]*g[1][i]/sum
这样我们统计一下上述数组并计算答案即可.
(我偷了下懒,把序列反转之后数值取了下反,就可以不写两遍CDQ,调用同一个函数就行了233)
代码实现:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int N=;
int n,toth,totv,st[N],top,f[][N];
struct node
{
int h,v,tim;
inline void read(){scanf("%d%d",&h,&v);}
}m[N];
inline bool mt1(const node &a,const node &b)
{
if(a.v==b.v&&a.h==b.h)return a.tim<b.tim;
return a.h==b.h?a.v<b.v:a.h<b.h;
}
inline bool mt2(const node &a,const node &b)
{return a.tim<b.tim;}
int bit[N];
double cnt[N],g[][N],ans[N];
inline int lowbit(int a){return a&-a;}
inline void add(int a,int b,double c)
{
while(a<=totv)
{
if(bit[a]<b)bit[a]=b,cnt[a]=c;
else if(bit[a]==b)cnt[a]+=c;
a+=lowbit(a);
}
}
inline void query(int a,int &b,double &c)
{
b=,c=0.0;
while(a)
{
if(bit[a]>b)b=bit[a],c=cnt[a];
else if(bit[a]==b)c+=cnt[a];
a-=lowbit(a);
}
}
inline void clear(int a)
{
while(a<=totv)
{
if(!bit[a])return;
bit[a]=,cnt[a]=0.0,a+=lowbit(a);
}
}
inline void CDQ(int l,int r,int o)
{
if(l==r)return;
register int i,mi=l+r>>;
CDQ(l,mi,o);
sort(m+l,m+r+,mt1);
int x=;double u=0.0;
for(i=l;i<=r;++i)
{
if(m[i].tim<=mi)
add(m[i].v,f[o][m[i].tim],g[o][m[i].tim]);
else
{
query(m[i].v,x,u);
if(x+>f[o][m[i].tim])
f[o][m[i].tim]=x+,g[o][m[i].tim]=u;
else if(x+==f[o][m[i].tim])
g[o][m[i].tim]+=u;
}
}
for(i=l;i<=r;++i)
if(m[i].tim<=mi)clear(m[i].v);
sort(m+l,m+r+,mt2);
CDQ(mi+,r,o);
}
inline void intn()
{
register int i;
for(i=;i<=n;++i)st[i]=m[i].h;
sort(st+,st+n+),toth=unique(st+,st+n+)-st-;
for(i=;i<=n;++i)
m[i].h=lower_bound(st+,st+toth+,m[i].h)-st;
for(i=;i<=n;++i)st[i]=m[i].v;
sort(st+,st+n+),totv=unique(st+,st+n+)-st-;
for(i=;i<=n;++i)
m[i].v=lower_bound(st+,st+totv+,m[i].v)-st;
}
int main()
{
register int i,j;scanf("%d",&n);
for(i=n;i;--i)m[i].read();
intn();
for(i=;i<=n;++i)
m[i].tim=i,f[][i]=f[][i]=g[][i]=g[][i]=;
CDQ(,n,);
reverse(m+,m+n+);
for(i=;i<=n;++i)
m[i].tim=i,m[i].h=toth-m[i].h+,m[i].v=totv-m[i].v+;
CDQ(,n,);
int maxn=;double sum=;
for(i=;i<=n;++i)
{
if(maxn<f[][i])maxn=f[][i],sum=g[][i];
else if(f[][i]==maxn)sum+=g[][i];
}
printf("%d\n",maxn);
for(i=;i<=n;++i)
{
if(f[][n-i+]+f[][i]-==maxn)
ans[i]=g[][n-i+]*g[][i]/sum;
else ans[i]=0.0;
}
for(i=;i<n;++i)printf("%.5lf ",ans[i]);
printf("%.5lf",ans[n]);
}
[BZOJ2244][SDOI2011]拦截导弹 CDQ分治的更多相关文章
- BZOJ2244: [SDOI2011]拦截导弹(CDQ分治,二维LIS,计数)
Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高 ...
- bzoj 2244: [SDOI2011]拦截导弹 cdq分治
2244: [SDOI2011]拦截导弹 Time Limit: 30 Sec Memory Limit: 512 MBSec Special JudgeSubmit: 237 Solved: ...
- BZOJ 2244: [SDOI2011]拦截导弹 (CDQ分治 三维偏序 DP)
题意 略- 分析 就是求最长不上升子序列,坐标取一下反就是求最长不下降子序列,比较大小是二维(h,v)(h,v)(h,v)的比较.我们不看概率,先看第一问怎么求最长不降子序列.设f[i]f[i]f[i ...
- BZOJ 2244: [SDOI2011]拦截导弹 [CDQ分治 树状数组]
传送门 题意:三维最长不上升子序列以及每个元素出现在最长不上升子序列的概率 $1A$了好开心 首先需要从左右各求一遍,长度就是$F[0][i]+F[1][i]-1$,次数就是$G[0][i]*G[1] ...
- BZOJ 2244 [SDOI2011]拦截导弹 ——CDQ分治
三维偏序,直接CDQ硬上. 正反两次CDQ统计结尾的方案数,最后统计即可. #include <cstdio> #include <cstring> #include < ...
- BZOJ2244 [SDOI2011]拦截导弹 【cdq分治 + 树状数组】
题目 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其 ...
- bzoj2244[SDOI2011]拦截导弹
http://www.lydsy.com/JudgeOnline/problem.php?id=2244 第$i$个导弹看成一个三元组$(i,h_i,v_i)$ 其实就是最长上升子序列的问题. 我们分 ...
- bzoj千题计划292:bzoj2244: [SDOI2011]拦截导弹
http://www.lydsy.com/JudgeOnline/problem.php?id=2244 每枚导弹成功拦截的概率 = 包含它的最长上升子序列个数/最长上升子序列总个数 pre_len ...
- 【BZOJ2244】[SDOI2011]拦截导弹(CDQ分治)
[BZOJ2244][SDOI2011]拦截导弹(CDQ分治) 题面 BZOJ 洛谷 题解 不难发现这就是一个三维偏序+\(LIS\)这样一个\(dp\). 那么第一问很好求,直接\(CDQ\)分治之 ...
随机推荐
- requests.get()解析
1.requests.get(url, params=None, headers=None, cookies=None, auth=None, timeout=None) Sends a GET re ...
- 17-使用公共 Registry
Docker Hub 是 Docker 公司维护的公共 Registry.用户可以将自己的镜像保存到 Docker Hub 免费的 repository 中.如果不希望别人访问自己的镜像,也可以购买私 ...
- 浏览器初始页面设置及被hao123劫持解决办法
最近在用浏览器时打开初始页面都是hao123,喵喵喜欢简单干净的页面,就去设置初始页面. 此处放置初始页面参考(并不太难): https://jingyan.baidu.com/article/11c ...
- Netty源码分析第4章(pipeline)---->第7节: 前章节内容回顾
Netty源码分析第四章: pipeline 第七节: 前章节内容回顾 我们在第一章和第三章中, 遗留了很多有关事件传输的相关逻辑, 这里带大家一一回顾 首先看两个问题: 1.在客户端接入的时候, N ...
- MySql 赋值操作符"="与":="
MySql小点心—1.赋值操作符"="与":=" 对于刚接触到mysql的程序员来说,会对这两个符号有疑问,因为会发现有的代码里用这个有的用另一个. 当然他们是 ...
- 在Web Page中包含PHP代码
PHP代码可以出现在Web Page的任何位置,甚至在HTML的标签里面也可以.有4中方式在Web Page中包含PHP代码: 使用<?php ... ?>标签 <!doctype ...
- Scrum Meeting 2 -2014.11.2
今天大家读完代码后又聚在了一块讨论了许多.确定了重点的任务和分工细节.提出了许多问题和改进的方案.还有讨论分析了关于团队作业 - 软件分析和用户需求调查,初步决定目标软件为必应的输入法和词典,团队为争 ...
- No.110_第三次团队会议
前端的易帜 前端在整个软件中有着举足轻重的地位.前端设计一般可以理解为视觉设计,前端开发则是前台代码的实现. 随着科技水平的提高和生产力的提高,人民对于审美的要求逐渐增高.在没有科技壁垒的情况下,是否 ...
- iOS自学-UILabel常见属性
#import "ViewController.h" #import <CoreText/CoreText.h> @interface ViewController ( ...
- Scapy之ARP询问
引言 校园网中,有同学遭受永恒之蓝攻击,但是被杀毒软件查下,并知道了攻击者的ip也是校园网.所以我想看一下,这个ip是PC,还是路由器. 在ip视角,路由器和pc没什么差别. 实现 首先是构造arp报 ...