BZOJ2244 [SDOI2011]拦截导弹 【cdq分治 + 树状数组】
题目
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度、并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其拦截的导弹的飞行速度也不能大于前一发。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
在不能拦截所有的导弹的情况下,我们当然要选择使国家损失最小、也就是拦截导弹的数量最多的方案。但是拦截导弹数量的最多的方案有可能有多个,如果有多个最优方案,那么我们会随机选取一个作为最终的拦截导弹行动蓝图。
我方间谍已经获取了所有敌军导弹的高度和速度,你的任务是计算出在执行上述决策时,每枚导弹被拦截掉的概率。
输入格式
第一行包含一个正整数n,表示敌军导弹数量;
下面 行按顺序给出了敌军所有导弹信息:
第i+1行包含2个正整数hi和vi,分别表示第 枚导弹的高度和速度。
输出格式
输出包含两行。
第一行为一个正整数,表示最多能拦截掉的导弹数量;
第二行包含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≤n≤5*104, 1≤hi ,vi≤109;
均匀分布着约30%的数据,所有vi均相等。
均匀分布着约50%的数据,满足1≤hi ,vi≤1000。
题解
二维LIS
考虑cdq分治,套上树状数组可以得到答案
但是要算概率就有些麻烦了
先要算出总方案数,计算过程中记录,最后最大值的地方方案数之和就是总方案数
至于每个点有多少方案经过
我们反着再做一次LIS,这样一个点往前往后之和 - 1如果等于答案,那么就将往前往后方案数乘起来就是总的方案数
码着真tm累
#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
#define lbt(x) (x & -x)
#define mp(a,b) make_pair<double,double>(a,b)
#define cp pair<double,double>
using namespace std;
const int maxn = 50005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
struct node{int t,x,y; double f[2],g[2];}e[maxn],t[maxn];
inline bool operator <(const node& a,const node& b){
return a.x == b.x ? a.y < b.y : a.x < b.x;
}
inline bool cmp(const node& a,const node& b){
return a.t < b.t;
}
int b[maxn],tot,c[maxn],tt;
int getx(int x){return lower_bound(b + 1,b + 1 + tot,x) - b;}
int gety(int x){return lower_bound(c + 1,c + 1 + tt,x) - c;}
int n;
double mx[maxn],sum[maxn];
void upd(int u,double v,double s){
while (u <= tt){
if (v > mx[u]){
mx[u] = v;
sum[u] = s;
}
else if (v == mx[u])
sum[u] += s;
u += lbt(u);
}
}
cp query(int u){
cp re = mp(0,0);
while (u){
if (mx[u] > re.first){
re.first = mx[u];
re.second = sum[u];
}
else if (mx[u] == re.first)
re.second += sum[u];
u -= lbt(u);
}
return re;
}
void cls(int u){
while (u <= tt){
sum[u] = mx[u] = 0;
u += lbt(u);
}
}
void init(){
n = read();
for (int i = 1; i <= n; i++){
e[i].t = i;
e[i].x = b[i] = read();
e[i].y = c[i] = read();
}
sort(b + 1,b + 1 + n);
sort(c + 1,c + 1 + n);
tot = tt = 1;
for (int i = 2; i <= n; i++) if (b[i] != b[tot]) b[++tot] = b[i];
for (int i = 2; i <= n; i++) if (c[i] != c[tt]) c[++tt] = c[i];
for (int i = 1; i <= n; i++){
e[i].x = getx(e[i].x);
e[i].y = gety(e[i].y);
}
}
void cdq(int l,int r,int p){
if (l == r){
if (!e[l].f[p]) e[l].f[p] = e[l].g[p] = 1;
return;
}
int mid = l + r >> 1,li = l,ri = mid + 1;
for (int i = l; i <= r; i++){
if (e[i].t <= mid) t[li++] = e[i];
else t[ri++] = e[i];
}
for (int i = l; i <= r; i++) e[i] = t[i];
cdq(l,mid,p);
sort(e + l,e + mid + 1);
cp tmp; li = l; ri = mid + 1;
while (li <= mid && ri <= r){
if (e[li].x <= e[ri].x) upd(e[li].y,e[li].f[p],e[li].g[p]),li++;
else {
tmp = query(e[ri].y);
if (!tmp.first) {ri++; continue;}
if (tmp.first + 1 > e[ri].f[p]){
e[ri].f[p] = tmp.first + 1;
e[ri].g[p] = tmp.second;
}
else if (tmp.first + 1 == e[ri].f[p]){
e[ri].g[p] += tmp.second;
}
ri++;
}
}
while (ri <= r){
tmp = query(e[ri].y);
if (!tmp.first) {ri++; continue;}
if (tmp.first + 1 > e[ri].f[p]){
e[ri].f[p] = tmp.first + 1;
e[ri].g[p] = tmp.second;
}
else if (tmp.first + 1 == e[ri].f[p]){
e[ri].g[p] += tmp.second;
}
ri++;
}
for (int i = l; i < li; i++) cls(e[i].y);
cdq(mid + 1,r,p);
}
void solve(){
for (int i = 1; i <= n; i++){
e[i].x = tot - e[i].x + 1;
e[i].y = tt - e[i].y + 1;
}
sort(e + 1,e + 1 + n);
cdq(1,n,0);
for (int i = 1; i <= n; i++){
e[i].x = tot - e[i].x + 1;
e[i].y = tt - e[i].y + 1;
e[i].t = n - e[i].t + 1;
}
sort(e + 1,e + 1 + n);
cdq(1,n,1);
for (int i = 1; i <= n; i++) e[i].t = n - e[i].t + 1;
sort(e + 1,e + 1 + n,cmp);
double ans = 0,sum = 0;
for (int i = 1; i <= n; i++){
if (e[i].f[0] > ans){
ans = e[i].f[0];
sum = e[i].g[0];
}else if (e[i].f[0] == ans){
sum += e[i].g[0];
}
}
printf("%.lf\n",ans);
for (int i = 1; i <= n; i++){
if (e[i].f[0] + e[i].f[1] - 1 < ans) printf("0 ");
else printf("%.6lf ",e[i].g[0] * e[i].g[1] / sum);
}
}
int main(){
init();
solve();
return 0;
}
BZOJ2244 [SDOI2011]拦截导弹 【cdq分治 + 树状数组】的更多相关文章
- BZOJ 2244: [SDOI2011]拦截导弹 [CDQ分治 树状数组]
传送门 题意:三维最长不上升子序列以及每个元素出现在最长不上升子序列的概率 $1A$了好开心 首先需要从左右各求一遍,长度就是$F[0][i]+F[1][i]-1$,次数就是$G[0][i]*G[1] ...
- [BZOJ2244][SDOI2011]拦截导弹 CDQ分治
2244: [SDOI2011]拦截导弹 Time Limit: 30 Sec Memory Limit: 512 MB Special Judge Description 某国为了防御敌国的导弹 ...
- BZOJ2244: [SDOI2011]拦截导弹(CDQ分治,二维LIS,计数)
Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高 ...
- 【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 ...
- 【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 ...
- BZOJ 2683 简单题 cdq分治+树状数组
题意:链接 **方法:**cdq分治+树状数组 解析: 首先对于这道题,看了范围之后.二维的数据结构是显然不能过的.于是我们可能会考虑把一维排序之后还有一位上数据结构什么的,然而cdq分治却可以非常好 ...
- LOJ3146 APIO2019路灯(cdq分治+树状数组)
每个时刻都形成若干段满足段内任意两点可达.将其视为若干正方形.则查询相当于求历史上某点被正方形包含的时刻数量.并且注意到每个时刻只有O(1)个正方形出现或消失,那么求出每个矩形的出现时间和消失时间,就 ...
- BZOJ 4553 [Tjoi2016&Heoi2016]序列 ——CDQ分治 树状数组
考虑答案的构成,发现是一个有限制条件的偏序问题. 然后三个维度的DP,可以排序.CDQ.树状数组各解决一维. #include <map> #include <cmath> # ...
随机推荐
- Azure 项目构建 – 构建和部署 .NET 应用程序
本课程主要介绍了如何在 Azure 平台上快速构建和部署基于 .NET 语言的 Web 应用, 实践讲解如何使用 Azure 门户创建 Web 应用, 部署 ASP.NET 代码, 连接 Azure ...
- GoAccess参数选项
GoAccess - 1.2 Usage: goaccess [filename] [ options ... ] [-c][-M][-H][-q][-d][...]The following opt ...
- 4个Linux服务器监控工具
下面是我想呈现给你的4个强大的监控工具. htop – 交互式进程查看器 你可能知道在机器上查看实时进程的标准工具top.如果不知道,请运行$ top看看,运行$ man top阅读帮助手册. hto ...
- python中return和yield
def wx(): a = 'wx' b = '无邪' return a, b print(wx()) print(type(wx())) -----------执行结果--------------- ...
- 计算机图形学:贝塞尔曲线(Bezier Curve)
计算机图形学:贝塞尔曲线(Bezier Curve) 贝塞尔能由贝塞尔样条组合而成,也可产生更高维的贝塞尔曲面.
- 行内元素的padding和margin是否无效
html中元素分为三种:块级元素.行内元素(也叫内联元素),内联块级元素. 常用块级元素:<div>.<p>.<h1>...<h6>.<ol> ...
- 学习笔记(_huaji_)
假如我没有见过太阳,我也许会忍受黑暗. 如果我知道自己会在哪里死去,我就永远都不去那儿.失败的经历,其实也有它的价值. 人的过失会带来错误,但要制造真正的灾难还得用计算机. 嘴角微微上扬已不复当年轻狂 ...
- Python中读取txt文本出现:SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape问题解决
windows中的路径是反斜杠\,然而反斜杠\在python中有着转义字符的意义,所以在py文件中写windows文件路径的时候,要特别注意反斜杠\的使用. 下面有三种解决方式: 方式一:转义的方式 ...
- ubuntu下如何对接斗鱼直播
参考教程:https://www.cnblogs.com/liuxuzzz/p/5315998.html 大神写得挺细的,这里都不想再多说了! 为啥要做这个呢?可能真的只是为了好玩吧!!有兴趣直播的孩 ...
- docker系列之分区挂载和数据卷
容器中的文件系统是独立的, 一旦容器被删除, 则文件系统也会被删除. 如果想容器和实体机在文件系统层面打通, 可以把指定目录挂载到容器当中: docker run -d -p 5000:22 -v / ...