【[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 ...
随机推荐
- del
Before writing it I spent a fair amount of time on reviewing our chat-log. How silly. asljdfajsodfss ...
- 15、IO (转换流、缓冲流)
转换流概述 * A: 转换流概述 * a: 转换流概述 * OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节 * 将字符串按照指定的 ...
- Tempter of the Bone 搜索---奇偶性剪枝
Tempter of the Bone Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) ...
- git杂记-查看历史提交
普通查看:git log.输入q退出比较. $ git log commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon ...
- 停课+2week
可真是,累啊. 本以为停课之后会轻松一点,结果天天好累的说... 今天开始得去锻炼锻炼了... 已经好几次突然一阵晕眩了qwq... 希望我还能挺得住吧,至少要挺到WC结束啊... 这次,可是关系到我 ...
- Mac里用终端ssh远程连接Centos服务器
在mac终端下输入 ssh -l root *.*.*.* 就可以远程连接Centos服务器了,端口没变还是:22 如果改变端口用下面方法输入: ssh -p 448(你改变的端口) -l root( ...
- ionCube 安装
有些程序在php环境下运行需要安装ionCube Loader的扩展支持,得到如下提示 Site error: the ionCube PHP Loader needs to be installed ...
- LeetCode 531----Lonely Pixel I----两种算法之间性能的比较
Lonely Pixel I 两种算法之间的性能比较 今天参加LeetCode Weekly Contest 22,第二题 "Lonely Pixel I" 问题描述如下: Giv ...
- Maximum Product Subarray 最大连续乘积子集
Find the contiguous subarray within an array (containing at least one number) which has the largest ...
- 系统测试用例评审checklist
规则要素内容 使用范围 审查结果 “否”的理由 “免”的理由 规则 建议 是 否 免 规范性规则 用例是否按照公司规定的模板进行编写? √ 用例的 ...