BZOJ 2244: [SDOI2011]拦截导弹 (CDQ分治 三维偏序 DP)
题意
略…
分析
就是求最长不上升子序列,坐标取一下反就是求最长不下降子序列,比较大小是二维(h,v)(h,v)(h,v)的比较.我们不看概率,先看第一问怎么求最长不降子序列.设f[i]f[i]f[i]表示以iii结尾的最长不降子序列的长度,有f[i]=max(f[j]+1) ( 0≤j<i,hj≤hi,vj≤vi )f[i]=max(f[j]+1)\ (\ 0\le j<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≤nf[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)的更多相关文章
- bzoj 2244: [SDOI2011]拦截导弹 cdq分治
2244: [SDOI2011]拦截导弹 Time Limit: 30 Sec Memory Limit: 512 MBSec Special JudgeSubmit: 237 Solved: ...
- BZOJ 2244 [SDOI2011]拦截导弹 ——CDQ分治
三维偏序,直接CDQ硬上. 正反两次CDQ统计结尾的方案数,最后统计即可. #include <cstdio> #include <cstring> #include < ...
- BZOJ 2244: [SDOI2011]拦截导弹 [CDQ分治 树状数组]
传送门 题意:三维最长不上升子序列以及每个元素出现在最长不上升子序列的概率 $1A$了好开心 首先需要从左右各求一遍,长度就是$F[0][i]+F[1][i]-1$,次数就是$G[0][i]*G[1] ...
- BZOJ 2244: [SDOI2011]拦截导弹 DP+CDQ分治
2244: [SDOI2011]拦截导弹 Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截 ...
- [BZOJ2244][SDOI2011]拦截导弹 CDQ分治
2244: [SDOI2011]拦截导弹 Time Limit: 30 Sec Memory Limit: 512 MB Special Judge Description 某国为了防御敌国的导弹 ...
- bzoj 2244 [SDOI2011]拦截导弹(DP+CDQ分治+BIT)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2244 [题意] 给定n个二元组,求出最长不上升子序列和各颗导弹被拦截的概率. [思路] ...
- BZOJ 2244 [SDOI2011]拦截导弹 (三维偏序CDQ+线段树)
题目大意: 洛谷传送门 不愧为SDOI的duliu题 第一问?二元组的最长不上升子序列长度?裸的三维偏序问题,直接上$CDQ$ 由于是不上升,需要查询某一范围的最大值,并不是前缀最大值,建议用线段树实 ...
- bzoj 2244 [SDOI2011]拦截导弹(dp+CDQ+树状数组)
传送门 题解 看了半天完全没发现这东西和CDQ有什么关系…… 先把原序列翻转,求起来方便 然后把每一个位置表示成$(a,b,c)$其中$a$表示位置,$b$表示高度,$c$表示速度,求有多少个位置$a ...
- bzoj 2244: [SDOI2011]拦截导弹
#include<cstdio> #include<iostream> #include<algorithm> #define M 100009 using nam ...
随机推荐
- 2019牛客多校赛第一场 补题 I题
I题 Points Division 题意: 给你n个点,每个点有坐标(xi,yi)和属性(ai,bi),将点集划分为两个集合, 任意 A 集合的点 i 和 B 集合点 j, 不允许 xi > ...
- (模板)求逆矩阵luoguP4783
题目链接:https://www.luogu.org/problem/P4783 题意:求矩阵的逆. 思路:高斯消元法求矩阵的逆,n为400,卡常,我是开了O2优化才AC的.. AC代码: #incl ...
- Javaweb入门 JDBC第一天
JDBC的定义和作用 DBC(Java DataBase Connectivity) Java数据库连接, 其实就是利用Java语言/程序连接并访问数据库的一门技术. 之前我们可以通过cmd或者nav ...
- 超级简单的requests模块教程
在web后台开发过程中,会遇到需要向第三方发送http请求的场景,python中的requests库可以很好的满足这一要求,这里简要记录一下requests模块的使用! 说明: 这里主要记录一下req ...
- Pycharm 配置houdini
一.houdini开发环境配置 1.添加Python可执行文件 2.设置代码自动补全 刚刚添加的Python.exe,右侧点击加号,依次添加以上长方形中的文件,路径会根据个人安装路径有所变化,后面的目 ...
- springboot加载application.yml文件null
话不多说,直接上代码 本人项目为maven项目 以下是项目结构 pom.xml文件 <?xml version="1.0" encoding="UTF-8" ...
- Django的URLconf
URL 概要 我们要在Django项目中为应用程序设计URL,我们可以创建一个名为URLconf(通常为urls.py)的Python模块.这个模块是纯Python代码,是一个简单的正则表达式到Pyt ...
- SysInternals提供了一个工具RamMap,可以查看内存的具体使用情况
SysInternals提供了一个工具RamMap,可以查看内存的具体使用情况.如果发现是Paged Pool和Nonpaged Pool占用过大,可以用另一个工具poolmon来查看占用内存的驱动T ...
- 轻松搭建CAS 5.x系列(1)-使用cas overlay搭建SSO SERVER服务端
概要说明 cas的服务端搭建有两种常用的方式: 1. 基于源码的基础上构建出来的 2. 使用WAR overlay的方式来安装 官方推荐使用第二种,配置管理方便,以后升级也容易.本文就是使用第 ...
- 1-MySQL DBA笔记-理解MySQL
第一部分 入门篇 本篇首先介绍MySQL的应用领域.基础架构和版本,然后介绍MySQL的基础知识,如查询的执行过程.权限机制.连接.存储引擎,最后阐述一些基础概念. 第1章 理解MySQL 本章将介绍 ...