题意

略…

分析

就是求最长不上升子序列,坐标取一下反就是求最长不下降子序列,比较大小是二维(h,v)(h,v)(h,v)的比较.我们不看概率,先看第一问怎么求最长不降子序列.设f[i]f[i]f[i]表示以iii结尾的最长不降子序列的长度,有f[i]=max(f[j]+1) ( 0≤j&lt;i,hj≤hi,vj≤vi )f[i]=max(f[j]+1)\ (\ 0\le j&lt;i,h_j\le h_i,v_j\le v_i\ )f[i]=max(f[j]+1) ( 0≤j<i,hj​≤hi​,vj​≤vi​ )那这就是一个三维偏序问题,只需要第一维CDQCDQCDQ,第二维排序,第三维用树状数组维护就行了.

要求概率,再定义g[i]g[i]g[i]表示以iii开始的最长不降子序列的长度.要求g[i]g[i]g[i]就坐标取反从nnn到111再做一次DPDPDP就行了.我们再设[0][0][0]表示序列长度,[1][1][1]表示这个长度的序列的方案.那对于iii点在最长不降子序列上的概率就是 f[i][1]∗g[i][1] ( f[i][0]+g[i][0]−1=LIS )∑1≤j≤nf[j][1] ( f[j][0]=LIS )\frac{f[i][1]*g[i][1]\ (\ f[i][0]+g[i][0]-1=LIS\ )}{\sum_{1\le j\le n} f[j][1]\ (\ f[j][0]=LIS\ )}∑1≤j≤n​f[j][1] ( f[j][0]=LIS )f[i][1]∗g[i][1] ( f[i][0]+g[i][0]−1=LIS )​分母其实就是总的最长上升子序列数量.

时间复杂度O(nlog2n)O(nlog^2n)O(nlog2n)

第一次写这样的CDQCDQCDQ,感觉好强…(是我太菜)

CODE

其实CDQCDQCDQ分治和树状数组都要离散化,但是标号本来就是1...n1...n1...n,就只用离散化vvv了.

代码还是蛮短的

#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<class T>inline void read(T &res) {
char ch; int flg = 1; for(;!isdigit(ch=getchar());)if(ch=='-')flg=-flg;
for(res=ch-'0';isdigit(ch=getchar());res=res*10+ch-'0'); res*=flg;
}
const int MAXN = 50005;
int n, bin[MAXN], tot, indx, stk[MAXN];
struct node { //写一个结构体
int x; double y; //方案数要用double不然会溢出
node() { x = y = 0; }
node(int _x, double _y):x(_x), y(_y){}
inline bool operator <(const node &o)const { return x < o.x; }
}T[MAXN];
inline void chkmax(node &A, const node &B) {
if(B < A) return;
if(A < B) A = B;
else A.y += B.y;
}
inline void upd(int x, node val) {
while(x <= tot) {
if(val.x > T[x].x) {
if(!T[x].x) stk[++indx] = x; //第一次修改就进栈
T[x] = val;
}
else if(val.x == T[x].x) T[x].y += val.y;
x += x&-x;
}
}
inline node qsum(int x) {
node res;
while(x) chkmax(res, T[x]), x -= x&-x;
return res;
}
struct Node { int i, h, v; node f; };
inline bool cmp2(const Node &A, const Node &B) { return A.h == B.h ? A.i < B.i : A.h < B.h; }
inline bool cmp(const Node &A, const Node &B) { return A.i < B.i; }
struct CDQ {
Node a[MAXN], tmp[MAXN];
void cdq(int l, int r) {
if(l == r) { if(!a[l].f.x || !a[l].f.y) a[l].f.x = a[l].f.y = 1; return; }
int mid = (l + r) >> 1;
int L = l, R = mid+1;
for(int i = l; i <= r; ++i) //分成左右两边
if(a[i].i <= mid) tmp[L++] = a[i];
else tmp[R++] = a[i];
for(int i = l; i <= r; ++i) a[i] = tmp[i];
cdq(l, mid);
sort(a + l, a + mid + 1, cmp2); L = l;
for(int i = mid+1; i <= r; ++i) {
while(L <= mid && a[i].h >= a[L].h) upd(a[L].v, a[L].f), ++L;
node res = qsum(a[i].v);
if(!res.x) continue;
++res.x, chkmax(a[i].f, res);
}
while(indx) T[stk[indx--]] = node(0, 0); //清零树状数组
cdq(mid+1, r);
}
}dp[2];
int main () {
read(n);
for(int i = 1; i <= n; ++i) {
dp[0].a[i].i = i, read(dp[0].a[i].h), read(dp[0].a[i].v);
dp[0].a[i].h *= -1, dp[0].a[i].v *= -1;
bin[++tot] = dp[0].a[i].v;
}
sort(bin + 1, bin + tot + 1); //只离散化V
tot = unique(bin + 1, bin + tot + 1) - bin - 1;
for(int i = 1; i <= n; ++i) {
dp[0].a[i].v = lower_bound(bin + 1, bin + tot + 1, dp[0].a[i].v) - bin;
dp[1].a[n-i+1].i = n-i+1;
dp[1].a[n-i+1].h = -dp[0].a[i].h;
dp[1].a[n-i+1].v = tot-dp[0].a[i].v+1;
}
sort(dp[0].a + 1, dp[0].a + n + 1, cmp2), dp[0].cdq(1, n);
sort(dp[1].a + 1, dp[1].a + n + 1, cmp2), dp[1].cdq(1, n); //做两次
sort(dp[0].a + 1, dp[0].a + n + 1, cmp);
sort(dp[1].a + 1, dp[1].a + n + 1, cmp); //重排序为 1~n
node Ans;
for(int i = 1; i <= n; ++i)
chkmax(Ans, dp[0].a[i].f);
printf("%d\n", Ans.x);
for(int i = 1; i <= n; ++i)
if(dp[0].a[i].f.x + dp[1].a[n-i+1].f.x - 1 < Ans.x) printf("%.6f ", 0.0);
else printf("%.6f ", dp[0].a[i].f.y*dp[1].a[n-i+1].f.y/Ans.y);
return 0;
}

BZOJ 2244: [SDOI2011]拦截导弹 (CDQ分治 三维偏序 DP)的更多相关文章

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

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

  2. BZOJ 2244 [SDOI2011]拦截导弹 ——CDQ分治

    三维偏序,直接CDQ硬上. 正反两次CDQ统计结尾的方案数,最后统计即可. #include <cstdio> #include <cstring> #include < ...

  3. BZOJ 2244: [SDOI2011]拦截导弹 [CDQ分治 树状数组]

    传送门 题意:三维最长不上升子序列以及每个元素出现在最长不上升子序列的概率 $1A$了好开心 首先需要从左右各求一遍,长度就是$F[0][i]+F[1][i]-1$,次数就是$G[0][i]*G[1] ...

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

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

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

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

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

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

  7. BZOJ 2244 [SDOI2011]拦截导弹 (三维偏序CDQ+线段树)

    题目大意: 洛谷传送门 不愧为SDOI的duliu题 第一问?二元组的最长不上升子序列长度?裸的三维偏序问题,直接上$CDQ$ 由于是不上升,需要查询某一范围的最大值,并不是前缀最大值,建议用线段树实 ...

  8. bzoj 2244 [SDOI2011]拦截导弹(dp+CDQ+树状数组)

    传送门 题解 看了半天完全没发现这东西和CDQ有什么关系…… 先把原序列翻转,求起来方便 然后把每一个位置表示成$(a,b,c)$其中$a$表示位置,$b$表示高度,$c$表示速度,求有多少个位置$a ...

  9. bzoj 2244: [SDOI2011]拦截导弹

    #include<cstdio> #include<iostream> #include<algorithm> #define M 100009 using nam ...

随机推荐

  1. 《MIT 6.828 Lab1: Booting a PC》实验报告

    <MIT 6.828 Lab1: Booting a PC>实验报告 本实验的网站链接见:Lab 1: Booting a PC. 实验内容 熟悉x86汇编语言.QEMU x86仿真器.P ...

  2. Servlet的request和response

    SERVLET API中forward() 与redirect()的区别?  答:前者仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址:后者则是完全的跳转,浏览器将会得到跳转的地址 ...

  3. C++ 简单实现 依赖注入(IOC)

    由于C++ 不支持“反射机制”, 在C++中需要实现依赖注入或控制反转需要增加辅助程序.例如在Windows 开发程序中根据类名动态创建对象,需要在类定义中增加宏.本文主要介绍C++ Ioc的一种实现 ...

  4. axios 跨域携带cookie设置

    import axios from 'axios' // 创建axios实例 const service = axios.create({ baseURL: process.env.BASE_API, ...

  5. Spring ——获取IOC容器时,构造方法、set方法、类方法执行顺序

    1,首先,我们在ApplicationContext.xml中会写下下面类的标示: <bean id="helloword" class="com.xt.frist ...

  6. 故事板(StoryBoards)和动画(Animations)

    Silverlight & Blend动画设计系列五:故事板(StoryBoards)和动画(Animations) 正如你所看到的,Blend是一个非常强大的节约时间的设计工具,在Blend ...

  7. JS写斐波那契数列的几种方法

    斐波那契数,指的是这样一个数列:1.1.2.3.5.8.13.21.……在数学上,斐波那契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=Fn-1+Fn-2(n>=2,n∈N*),用文字 ...

  8. js Indexof的用法

    JavaScript中indexOf()函数 JavaScript中indexOf()函数方法返回一个整数值,指出  String 对象内子字符串的开始位置.如果没有找到子字符串,则返回 -1.如果 ...

  9. ES6入门:数据劫持、Proxy、Reflect

    什么是数据劫持 Object数据劫持实现原理 Array数据劫持的实现原理 Proxy.Reflect 一.什么是数据劫持 定义:访问或者修改对象的某个属性时,在访问和修改属性值时,除了执行基本的数据 ...

  10. 命令行工具--LLDP

    目录 命令行工具--LLDP 一.场景引入 二.什么是LLDP? 三.在CentOS上安装LLDP 四.命令详解 五.脚本 命令行工具--LLDP 一.场景引入 有的时候,我们需要知道服务器上联交换机 ...