【LG2481】[SDOI2011]拦截导弹
【LG2481】[SDOI2011]拦截导弹
题面
题解
可以看出第一问就是一个有关偏序的\(LIS\),很显然可以用\(CDQ\)优化
关键在于第二问
概率\(P_i=\) \(总LIS数\) / \(经过i的LIS数\)
分别正反跑两遍\(CDQ\)可以统计出分别以\(i\)为终点和起点的\(LIS\)数
乘起来就是经过\(i\)的方案数
比较坑的一点是\(long\) \(long\)存不下,要用\(double\)
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
namespace IO {
const int BUFSIZE = 1 << 20;
char ibuf[BUFSIZE], *is = ibuf, *it = ibuf;
inline char gc() {
if (is == it) it = (is = ibuf) + fread(ibuf, 1, BUFSIZE, stdin);
return *is++;
}
}
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (ch != '-' && (ch > '9' || ch < '0')) ch = IO::gc();
if (ch == '-') w = -1 , ch = IO::gc();
while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = IO::gc();
return w * data;
}
const int MAX_N = 50005;
struct Node {int h, v, i; } t[MAX_N]; int N;
bool cmp_h(const Node &a, const Node &b) { return a.h > b.h; }
bool cmp_v(const Node &a, const Node &b) { return a.v > b.v; }
bool cmp_i(const Node &a, const Node &b) { return a.i < b.i; }
inline int lb(int x) { return x & -x; }
int c[MAX_N]; double w[MAX_N];
void add(int x, int v, double W) {
while (x <= N) {
if (v == c[x]) w[x] += W;
else if (v > c[x]) c[x] = v, w[x] = W;
x += lb(x);
}
}
int sum(int x) {
int res = 0;
while (x > 0) res = max(res, c[x]), x -= lb(x);
return res;
}
double sum(int x, int v) {
double res = 0;
while (x > 0) res += (c[x] == v) ? w[x] : 0, x -= lb(x);
return res;
}
void Set(int x) { while (x <= N) c[x] = w[x] = 0, x += lb(x); }
int f[2][MAX_N]; double g[2][MAX_N];
void Div(int l, int r, int type) {
if (l == r) return ;
sort(&t[l], &t[r + 1], cmp_i);
if (type) reverse(&t[l], &t[r + 1]);
int mid = (l + r) >> 1;
Div(l, mid, type);
sort(&t[l], &t[mid + 1], cmp_h);
sort(&t[mid + 1], &t[r + 1], cmp_h);
int j = l;
for (int i = mid + 1; i <= r; i++) {
while (j <= mid && t[j].h >= t[i].h)
add(N + 1 - t[j].v, f[type][t[j].i], g[type][t[j].i]), ++j;
int res = sum(N + 1 - t[i].v) + 1;
if (res > f[type][t[i].i])
f[type][t[i].i] = res, g[type][t[i].i] = sum(N + 1 - t[i].v, res - 1);
else if (res == f[type][t[i].i]) g[type][t[i].i] += sum(N + 1 - t[i].v, res - 1);
}
for (int i = l; i <= mid; i++) Set(N + 1 - t[i].v);
Div(mid + 1, r, type);
}
int Sh[MAX_N], toth, Sv[MAX_N], totv;
int main () {
N = gi();
for (int i = 1; i <= N; i++) t[i] = (Node){gi(), gi(), i};
for (int i = 1; i <= N; i++) Sh[++toth] = t[i].h;
sort(&Sh[1], &Sh[toth + 1]); toth = unique(&Sh[1], &Sh[toth + 1]) - Sh - 1;
for (int i = 1; i <= N; i++) t[i].h = lower_bound(&Sh[1], &Sh[toth + 1], t[i].h) - Sh;
for (int i = 1; i <= N; i++) Sv[++totv] = t[i].v;
sort(&Sv[1], &Sv[totv + 1]); totv = unique(&Sv[1], &Sv[totv + 1]) - Sv - 1;
for (int i = 1; i <= N; i++) t[i].v = lower_bound(&Sv[1], &Sv[totv + 1], t[i].v) - Sv;
for (int i = 1; i <= N; i++) f[0][i] = f[1][i] = g[0][i] = g[1][i] = 1;
Div(1, N, 0); reverse(&t[1], &t[N + 1]);
for (int i = 1; i <= N; i++) t[i].v = N + 1 - t[i].v, t[i].h = N + 1 - t[i].h;
Div(1, N, 1);
int ans = 0; double ss = 0;
for (int i = 1; i <= N; i++) ans = max(ans, f[0][i]);
for (int i = 1; i <= N; i++) if (f[0][i] == ans) ss += g[0][i];
printf("%d\n", ans);
for (int i = 1; i <= N; i++)
if (f[0][i] + f[1][i] - 1 != ans) printf("0.000000 ");
else printf("%0.6lf ", g[0][i] * g[1][i] / ss);
printf("\n");
return 0;
}
【LG2481】[SDOI2011]拦截导弹的更多相关文章
- bzoj 2244: [SDOI2011]拦截导弹 cdq分治
2244: [SDOI2011]拦截导弹 Time Limit: 30 Sec Memory Limit: 512 MBSec Special JudgeSubmit: 237 Solved: ...
- 【BZOJ2244】[SDOI2011]拦截导弹(CDQ分治)
[BZOJ2244][SDOI2011]拦截导弹(CDQ分治) 题面 BZOJ 洛谷 题解 不难发现这就是一个三维偏序+\(LIS\)这样一个\(dp\). 那么第一问很好求,直接\(CDQ\)分治之 ...
- [BZOJ2244][SDOI2011]拦截导弹 CDQ分治
2244: [SDOI2011]拦截导弹 Time Limit: 30 Sec Memory Limit: 512 MB Special Judge Description 某国为了防御敌国的导弹 ...
- P2487 [SDOI2011]拦截导弹
题目 P2487 [SDOI2011]拦截导弹 做\(SDOI\)有种想评黑的感觉,果然还是太弱了 做法 独立写(调)代码三个小时祭 简化题目:求二维最长不上升子序列及每个点出现在最长不上升子序列概率 ...
- BZOJ 2244: [SDOI2011]拦截导弹 DP+CDQ分治
2244: [SDOI2011]拦截导弹 Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截 ...
- BZOJ2244 [SDOI2011]拦截导弹 【cdq分治 + 树状数组】
题目 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其 ...
- BZOJ2244: [SDOI2011]拦截导弹(CDQ分治,二维LIS,计数)
Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高 ...
- bzoj 2244 [SDOI2011]拦截导弹(DP+CDQ分治+BIT)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2244 [题意] 给定n个二元组,求出最长不上升子序列和各颗导弹被拦截的概率. [思路] ...
- bzoj千题计划292:bzoj2244: [SDOI2011]拦截导弹
http://www.lydsy.com/JudgeOnline/problem.php?id=2244 每枚导弹成功拦截的概率 = 包含它的最长上升子序列个数/最长上升子序列总个数 pre_len ...
随机推荐
- BZOJ5301:[CQOI2018]异或序列(莫队)
Description 已知一个长度为 n 的整数数列 a[1],a[2],…,a[n] ,给定查询参数 l.r ,问在 [l,r] 区间内,有多少连续子 序列满足异或和等于 k . 也就是说,对于所 ...
- tmux分屏
网上很多教程: 新手教程: tmux进入 ctrl + b 命令 % 纵向分屏 命令 方向键 切换 https://lukaszwrobel.pl/blog/tmux-tutorial-split-t ...
- tp3.2上一篇下一篇功能
1. 后台 //上一页 $map1['a_id'] = array('gt',$a_id); $map1['cate_id'] = array('eq',$cate_id); $front=$arc- ...
- 18、配置嵌入式servlet容器(2)
使用其他Servlet容器 -Jetty(长连接) -Undertow(不支持jsp) 替换为其他嵌入式Servlet容器 默认支持: Tomcat(默认使用) Jetty: <depend ...
- Vue 问题记录
Vue 问题记录 汇总日常开发中遇到的关于vue的问题 VeeValidator 语言设置 校验消息默认是英文的,定义中文或其他语言的错误提示消息 import VeeValidate from 'v ...
- logback配置与使用(2)
转载:yaoh371 的logback.xml常用配置 <?xml version="1.0" encoding="UTF-8"?> <!-- ...
- mybaitis动态sql利用bind标签代替%拼接完成模糊查询
Oracle中使用bind的写法 <select id="selectUser" resultType="user" parameterType=&quo ...
- WIN10下的Docker安装
1.什么是Docker Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱 ...
- IOS开发数据存储篇—IOS中的几种数据存储方式
IOS开发数据存储篇—IOS中的几种数据存储方式 发表于2016/4/5 21:02:09 421人阅读 分类: 数据存储 在项目开发当中,我们经常会对一些数据进行本地缓存处理.离线缓存的数据一般都 ...
- oracle使用DBMS_RANDOM包生成随机数据
(一)DBMS_RANDOM包信息 DBMS_RANDOM包包含3个存储过程,4个函数,1个类型,一共8个模块,如下. SQL> desc dbms_random Element Type -- ...