【[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 ...
随机推荐
- Knockout.js Text绑定
<head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8&quo ...
- SQL Server使用ROW_NUMBER进行快速分页查询
DECLARE @pageSize INTDECLARE @pageIndex INT --第4页,每页显示10条数据SET @pageSize = 10SET @pageIndex = 4 SELE ...
- [Linux]C语言Linux系统编程创建进程
1.进程ID 每一个进程都由一个唯一的标识符表示,即进程ID,简称pid.系统保证在某时刻每个pid都是唯一的. 1.1分配进程ID 缺省情况下,内核将进程ID的最大值限制为32768,可以在此处设置 ...
- HDU 1575 Tr A----矩阵相乘题。
Tr A Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- poj Strange Way to Express Integers 中国剩余定理
Strange Way to Express Integers Time Limit: 1000MS Memory Limit: 131072K Total Submissions: 8193 ...
- JDBC增加、更新、删除数据
JDBC增加.更新.删除数据 st.executeUpdate(sql) 进行插入.更新.删除操作返回的是受影响的记录的条数 注意:输入的sql语句中,vachar类型记住加单引号 完整代码如下: p ...
- java设计模式-----8、策略模式
Strategy模式也叫策略模式是行为模式之一,它对一系列的算法加以封装,为所有算法定义一个抽象的算法接口,并通过继承该抽象算法接口对所有的算法加以封装和实现,具体的算法选择交由客户端决定(策略).S ...
- css,js移动资源
随着移动市场的逐步扩大及相关技术的日趋完善,对前端开发提出了新的岗位要求,在继承前人成果的基础上需要在新的历史条件下有新的创新.移动端的开发,虽然没有IE6众多问题的折磨,但是多平台,多设备的兼容,也 ...
- 数组实例 find和filter差异
const list01 = [{'name':'No1',age:20},{'name':'No2',age:21},{'name':'No3',age:20}]; let list02 = lis ...
- vue-cli构建项目 npm run build后应该怎么运行在本地查看效果
问题: 就是 bulid 打包后,想本地看看效果,本地看不了.... 网上看到一个.... 具体更多在: http://www.dabaipm.cn/static/frontend/346.htm ...