【[SDOI2011]拦截导弹】
这道题是真的蛇皮
方案数要开\(double\)真的蛇皮
首先\(dp\)是非常容易看出来的
设\(dp[i]\)表示以\(i\)结尾的最长子序列
显然转移方程为
\]
暴力转移是\(O(n^2)\)的
同时第二问我们还需要求一个概率
非常简单,我们反正做一遍\(dp\),看看\(i\)之后能连接的最长子序列为多少
同时统计好两边的方案数,之后如果左右两边的长度拼起来等于最长的长度,那么就可以存在在答案里,于是概率就是\(\frac{\text{左边的方案数}\times\text{右边的方案数}}{\text{总方案数}}\)
之后核心就是求出方案数和子序列长度了
发现这就是一个三维偏序的问题,我们可以直接硬上\(CDQ\)分治
但是像板子里写的那样的\(CDQ\)是不行的,板子里的\(CDQ\)本质上后根遍历,所以用左边更新右边的时候\(dp\)数组并不能被更新全
于是略改一下板子,改成中根遍历,先处理左边,之后用左边的来更新右边的\(dp\)值,之后处理右边
这样就能够保证每一个位置被更新的时候其前面的位置都已经被更新了
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define re register
#define maxn 50005
#define lowbit(x) ((x)&(-x))
#define LL double
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
inline int read()
{
char c=getchar();
int x=0;
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9')
x=(x<<3)+(x<<1)+c-48,c=getchar();
return x;
}
int H[maxn],HH[maxn];
int V[maxn],to[maxn];
int n,tot;
int lf[maxn],rf[maxn];
LL ld[maxn],rd[maxn];
inline int find(int x)
{
int l=1,r=tot;
while(l<=r)
{
int mid=l+r>>1;
if(H[mid]==x) return mid;
if(H[mid]>x) r=mid-1;
else l=mid+1;
}
return 0;
}
struct Node
{
int v,h,ans,rk;
LL d;
}a[maxn];
inline int cmp(Node A,Node B)
{
if(A.v==B.v) return A.h<B.h;
return A.v<B.v;
}
inline int cop(Node A,Node B)
{
return A.rk<B.rk;
}
int c[maxn];
LL bit[maxn];
inline void add(int x,int y,LL val)
{
for(re int i=x;i<=tot;i+=lowbit(i))
{
if(c[i]>y) continue;
if(c[i]==y) bit[i]+=val;
if(c[i]<y) c[i]=y,bit[i]=val;
}
}
inline int ask(int x) {int now=-1;for(re int i=x;i;i-=lowbit(i)) if(c[i]) now=max(now,c[i]);return now;}
inline LL query(int x,int M) {LL now=0;for(re int i=x;i;i-=lowbit(i)) if(c[i]&&c[i]==M) now+=bit[i];return now;}
inline void clear(int x) {for(re int i=x;i<=tot;i+=lowbit(i)) c[i]=0,bit[i]=0;}
void CDQ(int s,int t)
{
if(s==t) return;
int mid=s+t>>1;
CDQ(s,mid);
std::sort(a+s,a+mid+1,cmp),std::sort(a+mid+1,a+t+1,cmp);
int i=s,j=mid+1;
while(i<=mid&&j<=t)
{
if(a[i].v<=a[j].v) add(a[i].h,a[i].ans,a[i].d),i++;
else
{
int now=ask(a[j].h);
if(now!=-1)
{
if(now+1>a[j].ans) a[j].ans=now+1,a[j].d=query(a[j].h,now);
else if(now+1==a[j].ans) a[j].d+=query(a[j].h,now);
}
j++;
}
}
while(j<=t)
{
int now=ask(a[j].h);
if(now!=-1)
{
if(now+1>a[j].ans) a[j].ans=now+1,a[j].d=query(a[j].h,now);
else if(now+1==a[j].ans) a[j].d+=query(a[j].h,now);
}
j++;
}
for(re int k=s;k<i;k++) clear(a[k].h);
std::sort(a+mid+1,a+t+1,cop);
CDQ(mid+1,t);
}
int main()
{
n=read();
for(re int i=1;i<=n;i++) V[i]=-1*read(),H[i]=-1*read(),HH[i]=H[i],a[i].rk=i;
std::sort(H+1,H+n+1);
tot=std::unique(H+1,H+n+1)-H-1;
for(re int i=1;i<=n;i++)
to[i]=find(HH[i]);
for(re int i=1;i<=n;i++) a[i].v=V[i],a[i].h=to[i],a[i].ans=1,a[i].d=1;
CDQ(1,n);
int ans=0;LL now=0;
for(re int i=1;i<=n;i++) ans=max(ans,a[i].ans);
for(re int i=1;i<=n;i++) if(ans==a[i].ans) now+=a[i].d;
printf("%d\n",ans);
for(re int i=1;i<=n;i++) lf[a[i].rk]=a[i].ans,ld[a[i].rk]=a[i].d;
for(re int i=1;i<=n;i++)
V[i]=-1*V[i],HH[i]=-1*HH[i],H[i]=HH[i];
std::sort(H+1,H+n+1);
tot=std::unique(H+1,H+n+1)-H-1;
for(re int i=1;i<=n;i++)
to[i]=find(HH[i]);
for(re int i=n;i;--i) a[n-i+1].v=V[i],a[n-i+1].h=to[i],a[n-i+1].rk=n-i+1,a[n-i+1].ans=1,a[n-i+1].d=1;
CDQ(1,n);
for(re int i=1;i<=n;i++) a[i].rk=n-a[i].rk+1;
for(re int i=1;i<=n;i++) rf[a[i].rk]=a[i].ans,rd[a[i].rk]=a[i].d;
for(re int i=1;i<=n;i++)
{
if(rf[i]+lf[i]-1==ans)
printf("%.5lf ",rd[i]*ld[i]/now);
else printf("0.00000 ");
}
return 0;
}
【[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 某国为了防御敌国的导弹 ...
- 【LG2481】[SDOI2011]拦截导弹
[LG2481][SDOI2011]拦截导弹 题面 洛谷 题解 可以看出第一问就是一个有关偏序的\(LIS\),很显然可以用\(CDQ\)优化 关键在于第二问 概率\(P_i=\) \(总LIS数\) ...
- 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 ...
随机推荐
- Swift函数_默认参数
swift中提供了默认参数功能,在声明函数时给参数指定默认值. 例: func inputStudentInfo(name:String,age:Int="26") { print ...
- Autocomplete 自动提示
<!doctype html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- Spring Boot学习笔记(五)整合mybatis
pom文件里添加依赖 <!-- 数据库需要的依赖 --> <dependency> <groupId>org.mybatis.spring.boot</gro ...
- 用手机访问管理mysql
移动办公的情况及需求越来越多,平时MySQL,Oracle,SQLServer等数据库的管理都要通过客户端工具操作,现在有一款基于web网页的软件:TreeSoft数据库管理系统,在服务器布署一套后, ...
- k:特殊的线性表—队列
队列的概念: 队列是另一种特殊的线性表,它的特殊性体现在其只允许在线性表的一端插入数据元素,在线性表的另一端删除数据元素(一般会采用在线性表的表尾那端(没被head指针所指的那端)插入数据元素,在线 ...
- is_array判断是否为数组
if(is_array($arr)){ echo "是数组"; }else{ echo "不是数组"; }
- JavaScript的进阶之路(七)客户端JavaScript知识点总结
一.客户端JavaScript主要是BOM DOM的操作和js脚本的兼容性.互用性.可访问性.安全性的应用.以及一些框架的引用. 二.BOM:浏览器对象模型 主要介绍window对象 1.定时器:se ...
- JavaScript的进阶之路(五)理解数组1
数组是值得有序结合,每个值叫做一个元素,每个元素的位置称为索引,索引从0开始. 在JavaScript中,数组是对象的特殊形式.继承自Array.prototype中的属性,有丰富的数组操作方法. 通 ...
- AE+C#实现:在SceneControl里打开和保存
来自:http://www.cnblogs.com/zhuxy/archive/2012/03/30/2424672.html 之前编写这段代码,发现一直没有C#编写的,现在贴出来,希望对大家有用 此 ...
- Node服务端极速搭建 - nvmhome
本文意在让你掌握极速搭建Node服务端(任何Project) $ whoami name: kelvin email: kelvv@outlook.com homepage: www.kelvv.co ...