【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]拦截导弹的更多相关文章

  1. bzoj 2244: [SDOI2011]拦截导弹 cdq分治

    2244: [SDOI2011]拦截导弹 Time Limit: 30 Sec  Memory Limit: 512 MBSec  Special JudgeSubmit: 237  Solved: ...

  2. 【BZOJ2244】[SDOI2011]拦截导弹(CDQ分治)

    [BZOJ2244][SDOI2011]拦截导弹(CDQ分治) 题面 BZOJ 洛谷 题解 不难发现这就是一个三维偏序+\(LIS\)这样一个\(dp\). 那么第一问很好求,直接\(CDQ\)分治之 ...

  3. [BZOJ2244][SDOI2011]拦截导弹 CDQ分治

    2244: [SDOI2011]拦截导弹 Time Limit: 30 Sec  Memory Limit: 512 MB  Special Judge Description 某国为了防御敌国的导弹 ...

  4. P2487 [SDOI2011]拦截导弹

    题目 P2487 [SDOI2011]拦截导弹 做\(SDOI\)有种想评黑的感觉,果然还是太弱了 做法 独立写(调)代码三个小时祭 简化题目:求二维最长不上升子序列及每个点出现在最长不上升子序列概率 ...

  5. BZOJ 2244: [SDOI2011]拦截导弹 DP+CDQ分治

    2244: [SDOI2011]拦截导弹 Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截 ...

  6. BZOJ2244 [SDOI2011]拦截导弹 【cdq分治 + 树状数组】

    题目 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其 ...

  7. BZOJ2244: [SDOI2011]拦截导弹(CDQ分治,二维LIS,计数)

    Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高 ...

  8. bzoj 2244 [SDOI2011]拦截导弹(DP+CDQ分治+BIT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2244 [题意] 给定n个二元组,求出最长不上升子序列和各颗导弹被拦截的概率. [思路] ...

  9. bzoj千题计划292:bzoj2244: [SDOI2011]拦截导弹

    http://www.lydsy.com/JudgeOnline/problem.php?id=2244 每枚导弹成功拦截的概率 = 包含它的最长上升子序列个数/最长上升子序列总个数 pre_len ...

随机推荐

  1. Python模块(进阶3)

    转载请标明出处: http://www.cnblogs.com/why168888/p/6411917.html 本文出自:[Edwin博客园] Python模块(进阶3) 1. python中模块和 ...

  2. MongoDB排序记录

    MongoDB sort()方法 要在MongoDB中排序文档,需要使用sort()方法. 该方法接受包含字段列表及其排序顺序的文档.使用指定排序顺序1和-1. 1用于升序,而-1用于降序. 语法 s ...

  3. Eclipse安装Sonarlint插件

    这里安装的是Sonarlint3.6.插件安装非常简单.插件比Sonar更为简单快捷. 一.首先通过点击Eclipse上方Help菜单会出现一个下拉列表,点击其中的Eclipse MarketPlac ...

  4. zabbix-agent安装

    1.下载yum源库 rpm -i http://repo.zabbix.com/zabbix/3.4/rhel/7/x86_64/zabbix-release-3.4-2.el7.noarch.rpm ...

  5. HDU 1250 Hat's Fibonacci(大数相加)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1250 Hat's Fibonacci Time Limit: 2000/1000 MS (Java/Ot ...

  6. Xcode菜单功能中文翻译

    Xcode菜单功能中文翻译 File  文件 Edit  编辑 View 视图 Navigate 导航 Editor 编辑 Product 产品 Window  窗口 Help 帮助 File  文件 ...

  7. Linq 表达

    Lambda 简单了解 //Lambda //匿名方法 //delegate (Student s) { return s.Age > 12 && s.Age < 20; ...

  8. stm32之remap

    1.GPIO的重映射属于AFIO,不同类型不同引脚数单片机情况不一样,比如下图: 2.AFIO 下面还分default/Remap,如果用到了remap就得使用: GPIO_PinRemapConfi ...

  9. insert插入数据

    insert 语法1 --插入的值需要用单引号引起来,否则字段插入会有问题,可能造成查询的时候查询不出结果 insert  into  表名 (列名1,列名2……)  ] values  ( '值1' ...

  10. dubbo配置注意

    API接口的路径在provider和consumer端的路径要一致