[BZOJ2244]:拦截导弹(DP+CDQ分治+树状数组)
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度、并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其拦截的导弹的飞行速度也不能大于前一发。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
在不能拦截所有的导弹的情况下,我们当然要选择使国家损失最小、也就是拦截导弹的数量最多的方案。但是拦截导弹数量的最多的方案有可能有多个,如果有多个最优方案,那么我们会随机选取一个作为最终的拦截导弹行动蓝图。
我方间谍已经获取了所有敌军导弹的高度和速度,你的任务是计算出在执行上述决策时,每枚导弹被拦截掉的概率。
输入格式
第一行包含一个正整数$n$,表示敌军导弹数量;
下面行按顺序给出了敌军所有导弹信息:
第$i+1$行包含$2$个正整数$h_i$和$v_i$,分别表示第$i$枚导弹的高度和速度。
输出格式
输出包含两行。
第一行为一个正整数,表示最多能拦截掉的导弹数量;
第二行包含$n$个$0$到$1$之间的实数,第$i$个数字表示第$i$枚导弹被拦截掉的概率(你可以保留任意多位有效数字)。
样例
样例输入
4
3 30
4 40
6 60
3 30
样例输出
2
0.33333 0.33333 0.33333 1.00000
数据范围与提示
对于$100%$的数据,$1\leqslant n\leqslant 5\times 10^4$,$1\leqslant h_i$ ,$v_i\leqslant 10^9$;
均匀分布着约$30%$的数据,所有$v_i$均相等。
均匀分布着约$50%$的数据,满足$1\leqslant h_i,v_i\leqslant 1,000$。
题解
这道题就是求一个三维的最长非上升子序列的长度($LDS$),肯定要用$CDQ$分治啦~
利用中序遍历的思想来进行$CDQ$分治,先处理左区间,再处理当前节点的值,最后处理右区间。
设$f_{1_i}$表示正序时$LDS$的长度,$g_{1_i}$表示个数,$f_{2_i}$和$g_{2_i}$则是逆序。
处理跟$CDQ$分治一样。
下面来讲一下如何统计答案:
第一问的答案就是$\max(f_{1_i})$。
第二问稍繁琐,考虑只有当$f_{1_i}+f_{2_i}-1=\max(f_{1_i})$时(减去重复计算的节点$i$),给节点才能成为$LDS$上的点,总方案数即为$g_{1_i}\times g_{2_i}$,答案即为$\frac{g_{1_i}\times g_{2_i}}{\sum \limits_{i=1}^{n}g_{1_i}(f_{1_i}=\max)}$。
代码时刻
#include<bits/stdc++.h>
using namespace std;
struct rec
{
int d;
int h;
int v;
pair<pair<int,double>,pair<int,double> >dp;
}e[50001];
int n;
int flag[50001],hmax,vmax;
int trmax[200001];
int ans;
double sum;
pair<int,double> tr[200000];//树状数组
bool cmpd(rec a,rec b){return a.d<b.d;}
bool cmph1(rec a,rec b){return a.h>b.h;}
bool cmph2(rec a,rec b){return a.h<b.h;}
bool cmpv(rec a,rec b){return a.v<b.v;}
int lowbit(int x){return x&-x;}
void mem(int x)//清空
{
for(int i=x;i<=n;i+=lowbit(i))
tr[i]=make_pair(0,0.0);
}
void add(int x,int l,double r)//插入
{
for(int i=x;i<=n;i+=lowbit(i))
if(tr[i].first<l)tr[i]=make_pair(l,r);
else if(tr[i].first==l)tr[i].second+=r;
}
pair<int,double> ask(int x)//查询
{
pair<int,double> res;
for(int i=x;i;i-=lowbit(i))
if(tr[i].first>res.first)res=tr[i];
else if(tr[i].first==res.first)res.second+=tr[i].second;
return res;
}
void cdq1(int l,int r)//正序CDQ
{
if(l==r)return;
int mid=(l+r)>>1;
cdq1(l,mid);
sort(e+l,e+mid+1,cmph1);
sort(e+mid+1,e+r+1,cmph1);
int i=mid+1,j=l;
for(;i<=r;i++)
{
while(j<=mid&&e[i].h<=e[j].h){add(vmax-e[j].v,e[j].dp.first.first,e[j].dp.first.second);j++;}
pair<int,double> frec=ask(vmax-e[i].v);
if(e[i].dp.first.first<=frec.first)
{
e[i].dp.first.first=frec.first+1;
e[i].dp.first.second=frec.second;
}
else if(e[i].dp.first.first==frec.first+1)e[i].dp.first.second+=frec.second;
}j--;
for(;j>=l;j--)mem(vmax-e[j].v);
sort(e+l,e+r+1,cmpd);
cdq1(mid+1,r);
}
void cdq2(int l,int r)//逆序CDQ
{
if(l==r)return;
int mid=(l+r)>>1;
cdq2(mid+1,r);
sort(e+l,e+mid+1,cmph2);
sort(e+mid+1,e+r+1,cmph2);
int i=l,j=mid+1;
for(;i<=mid;i++)
{
while(j<=r&&e[i].h>=e[j].h){add(e[j].v,e[j].dp.second.first,e[j].dp.second.second);j++;}
pair<int,double> frec=ask(e[i].v);
if(e[i].dp.second.first<=frec.first)
{
e[i].dp.second.first=frec.first+1;
e[i].dp.second.second=frec.second;
}
else if(e[i].dp.second.first==frec.first+1)e[i].dp.second.second+=frec.second;
}j--;
for(;j>mid;j--)mem(e[j].v);
sort(e+l,e+r+1,cmpd);
cdq2(l,mid);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
e[i].d=i;
scanf("%d%d",&e[i].h,&e[i].v);
e[i].dp.first.first=e[i].dp.second.first=1;
e[i].dp.first.second=e[i].dp.second.second=1.0;
}
sort(e+1,e+n+1,cmph2);
for(int i=1;i<=n;i++)//预处理h
{
if(e[i].h!=e[i-1].h)flag[0]++;
flag[i]=flag[0];
}
for(int i=1;i<=n;i++)
e[i].h=flag[i];
flag[0]=0;
sort(e+1,e+n+1,cmpv);
for(int i=1;i<=n;i++)//预处理v
{
if(e[i].v!=e[i-1].v)flag[0]++;
flag[i]=flag[0];
}
for(int i=1;i<=n;i++)
e[i].v=flag[i];
vmax=e[n].v+1;
sort(e+1,e+n+1,cmpd);
cdq1(1,n);
for(int i=1;i<=n;i++)//第一问
ans=max(ans,e[i].dp.first.first);
cdq2(1,n);
for(int i=1;i<=n;i++)
if(e[i].dp.first.first+e[i].dp.second.first==ans+1)
sum+=e[i].dp.first.second*e[i].dp.second.second;
sum/=(double)ans;
printf("%d\n",ans);
for(int i=1;i<=n;i++)//第二问
{
if(e[i].dp.first.first+e[i].dp.second.first==ans+1)
printf("%.7lf ",e[i].dp.first.second*e[i].dp.second.second/sum);
else printf("0.0000000 ");
}
return 0;
}
rp++
[BZOJ2244]:拦截导弹(DP+CDQ分治+树状数组)的更多相关文章
- BZOJ - 2244 拦截导弹 (dp,CDQ分治+树状数组优化)
题目链接 dp进阶之CDQ分治优化dp. 前置技能:dp基本功底,CDQ分治,树状数组. 问题等价于求二维最长上升子序列,是一个三维偏序问题(时间也算一维). 设$dp[i]=(l,x)$为以第i枚导 ...
- BZOJ2244 [SDOI2011]拦截导弹 【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 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能 ...
- BZOJ 1176 Mokia CDQ分治+树状数组
1176: [Balkan2007]Mokia Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 1854 Solved: 821[Submit][St ...
- 【bzoj3262】陌上花开 CDQ分治+树状数组
题目描述 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa&g ...
- BZOJ 2683 简单题 cdq分治+树状数组
题意:链接 **方法:**cdq分治+树状数组 解析: 首先对于这道题,看了范围之后.二维的数据结构是显然不能过的.于是我们可能会考虑把一维排序之后还有一位上数据结构什么的,然而cdq分治却可以非常好 ...
- LOJ3146 APIO2019路灯(cdq分治+树状数组)
每个时刻都形成若干段满足段内任意两点可达.将其视为若干正方形.则查询相当于求历史上某点被正方形包含的时刻数量.并且注意到每个时刻只有O(1)个正方形出现或消失,那么求出每个矩形的出现时间和消失时间,就 ...
- BZOJ 4553 [Tjoi2016&Heoi2016]序列 ——CDQ分治 树状数组
考虑答案的构成,发现是一个有限制条件的偏序问题. 然后三个维度的DP,可以排序.CDQ.树状数组各解决一维. #include <map> #include <cmath> # ...
随机推荐
- Jmeter响应数据显示乱码问题
Jmeter在访问接口的时候,响应内容如果有中文可能会显示乱码,原因应该是响应页面没有做编码处理,jmeter默认按照ISO-8859-1编码格式进行解析. 解决步骤: 现象:jmeter访问本地文件 ...
- 使用Oracle12c 以上的PDB创建数据库用户 密码过期的简单处理
1. 先通过监听查看PDB的名字 Windows 打开命令行: 输入命令 lsnrctl status 一般在如图示的最下面 2. 也可以通过GS的全局配置文件来查看 数据库连接SID信息. C:\P ...
- C++中对象的构造顺序
1,C++ 中的类可以定义多个对象,那么对象构造顺序是怎样的? 1,很多的 bug 是由对象的构造顺序造成的,虽然它不难: 2,对象的构造往往和构造函数牵涉在一起,构造函数的函数体又可能由非常复杂的程 ...
- c语言中字符串跨行书写的问题
字符串常量定义时的换行问题 如果我们在一行代码的行尾放置一个反斜杠,c语言编译器会忽略行尾的换行符,而把下一行的内容也算作是本行的内容.这里反斜杠起到了续行的作用. 如果我们不使 ...
- element ui中的一些小技巧
最近写公司的项目,这项目是vue和element ui搭建的, 做的是一套电力系统的管理平台. 遇到一个小麻烦,用过element ui 的都知道,使用element ui 弹框,点击空白处,默认是 ...
- iOS开发之详解剪贴板
关于UIMenuController的用法例子 今天终于搞明白了UIMenuController显示的相关内容,把源代码分享给大家! 要正常显示菜单,必须做到以下几点:1. -(BOOL)canBec ...
- idea的使用技巧
* 简介:程序员每日都会花费数小时使用ide编写和调试代码,其中很多操作都是机械重复且频率非常高,本着"工欲善其事必先利其器"的精神,闷头写代码之外花点时间研究一下自己用的ide, ...
- Array.prototype
Array.prototype 属性表示 Array 构造函数的原型,并允许您向所有Array对象添加新的属性和方法. /* 如果JavaScript本身不提供 first() 方法, 添加一个返回 ...
- MapReduce单机提交(待稿)
MR 提交方式源码 提交方式: 1,开发-> jar -> 上传到集群中的某一个节点 -> hadoop jar ooxx.jar ooxx in out 2,嵌入[linux,wi ...
- VB里面的字体颜色
颜色常数颜色常数 值 描述vbBlack &H0 黑色vbRed &HFF 红色vbGreen &HFF00 绿色vbYellow &HFFFF 黄色vbBlue &a ...