【题目链接】

http://www.lydsy.com/JudgeOnline/problem.php?id=2244

【题意】

给定n个二元组,求出最长不上升子序列和各颗导弹被拦截的概率。

【思路】

DP+CDQ分治+BIT

先把序列反转一下,lis求起来方便。

对于第一问,我们要求的是

f[i]=max{ f[j] },j<i,x[j]<x[i],y[j]<y[i]

发现需要满足的条件就是一个三维偏序,可以用CDQ分治求解

不难发现第二问其实就等于:一颗导弹所在的lis数/总的lis数。一个导弹所在的lis必须包含自己,所以我们设g[i]表示以i为结尾的lis总数,则有转移式:

g[i]=sigma{ g[j] }, j<i,x[j]<x[i],y[j]<y[i],f[j]+1=f[i]

依旧可以用CDQ分治求。注意到最后的一个f的关系,这时候只需要统计出之前的最大lis值再与f相比较就可以了(蒟蒻的我一直苦思冥想。。。

相似的可以求出g’f’。都是g f的相反定义,即以i开头的…

奇技淫巧:我们可以在反转一下并对序列取一下反,这样就都可以套用函数辣。貌似离散化之后跑得飞快,一跃直上rk3

【代码】

 #include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define FOR(a,b,c) for(int a=b;a<=c;a++)
using namespace std; const int N = 1e5+; struct Node {
int id,x,y;
bool operator<(const Node& rhs)const {
return x<rhs.x||(x==rhs.x&&y<rhs.y);
}
}q[N],t[N];
bool cmp(const Node& a,const Node& b)
{
return a.id<b.id;
} int f[][N]; double g[][N],ans[N];
int hash[N],tot,n; int read()
{
char c=getchar(); int x=; int f=;
while(!isdigit(c)){if(c=='-')f=-; c=getchar();}
while(isdigit(c)) x=x*+c-'',c=getchar();
return x*f;
} int t_f[N],tag[N],T; double t_g[N];
void add(int x,int f,double g)
{
for(;x<=tot;x+=x&-x) {
if(tag[x]!=T) {tag[x]=T;t_f[x]=;t_g[x]=;}
if(f>t_f[x]){t_f[x]=f;t_g[x]=g;}
else if(f==t_f[x]) t_g[x]+=g;
}
}
void query(int x,int& mx,double& sum)
{
mx=; sum=0.0;
for(;x;x-=x&-x) if(tag[x]==T){
if(t_f[x]>mx) {
mx=t_f[x]; sum=t_g[x];
} else if(t_f[x]==mx)
sum+=t_g[x];
}
} void solve(int l,int r,int ty)
{
if(l==r) {
if(!f[ty][l]){
f[ty][l]=; g[ty][l]=;
}
return ;
}
int mid=(l+r)>>;
int l1=l,l2=mid+,i,j,cnt=;
for(i=l;i<=r;i++) {
if(q[i].id<=mid) t[l1++]=q[i];
else t[l2++]=q[i];
}
memcpy(q+l,t+l,sizeof(Node)*(r-l+));
solve(l,mid,ty);
T++;
sort(q+mid+,q+r+);
for(i=mid+,j=l;i<=r;i++)
{
int id;
for(;j<=mid&&q[j].x<=q[i].x;j++) {
id=q[j].id; cnt++;
add(q[j].y,f[ty][id],g[ty][id]);
}
int mx; double sum;
query(q[i].y,mx,sum);
id=q[i].id;
if(mx>) {
if(mx+>f[ty][id]) {
f[ty][id]=mx+; g[ty][id]=sum;
} else if(mx+==f[ty][id]) {
g[ty][id]+=sum;
}
}
}
solve(mid+,r,ty);
l1=l,l2=mid+; int now=l;
while(l1<=mid||l2<=r) {
if(l2>r||l1<=mid&&q[l1]<q[l2]) t[now++]=q[l1++];
else t[now++]=q[l2++];
}
memcpy(q+l,t+l,sizeof(Node)*(r-l+));
} int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
n=read();
int mxx=;
FOR(i,,n)
{
q[i].x=read(),q[i].y=read();
hash[i]=q[i].y;
mxx=max(mxx,q[i].x);
}
sort(hash+,hash+n+);
tot=unique(hash+,hash+n+)-hash-;
FOR(i,,n)
q[i].y=lower_bound(hash+,hash+tot+,q[i].y)-hash;
reverse(q+,q+n+);
FOR(i,,n) q[i].id=i;
solve(,n,); sort(q+,q+n+,cmp);
reverse(q+,q+n+);
FOR(i,,n)
q[i].x=mxx-q[i].x+,q[i].y=tot-q[i].y+,
q[i].id=i;
solve(,n,);
int mx=; double sum=;
FOR(i,,n) {
int tmp=f[][i];
if(tmp>mx) {
mx=tmp; sum=g[][i]*g[][n-i+];
} else if(tmp==mx)
sum+=g[][i]*g[][n-i+];
}
printf("%d\n",mx);
for(int i=n;i;i--) {
if(f[][i]+f[][n-i+]-==mx) {
ans[i]=(g[][i]*g[][n-i+])/sum;
} else ans[i]=;
}
for(int i=n;i>;i--) printf("%.5lf ",ans[i]);
printf("%.5lf",ans[]);
return ;
}

bzoj 2244 [SDOI2011]拦截导弹(DP+CDQ分治+BIT)的更多相关文章

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

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

  2. 【BZOJ2244】[SDOI2011]拦截导弹(CDQ分治)

    [BZOJ2244][SDOI2011]拦截导弹(CDQ分治) 题面 BZOJ 洛谷 题解 不难发现这就是一个三维偏序+\(LIS\)这样一个\(dp\). 那么第一问很好求,直接\(CDQ\)分治之 ...

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

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

  4. BZOJ - 2244 拦截导弹 (dp,CDQ分治+树状数组优化)

    题目链接 dp进阶之CDQ分治优化dp. 前置技能:dp基本功底,CDQ分治,树状数组. 问题等价于求二维最长上升子序列,是一个三维偏序问题(时间也算一维). 设$dp[i]=(l,x)$为以第i枚导 ...

  5. BZOJ2244 [SDOI2011]拦截导弹 【cdq分治 + 树状数组】

    题目 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其 ...

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

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

  7. BZOJ 2244: [SDOI2011]拦截导弹 (CDQ分治 三维偏序 DP)

    题意 略- 分析 就是求最长不上升子序列,坐标取一下反就是求最长不下降子序列,比较大小是二维(h,v)(h,v)(h,v)的比较.我们不看概率,先看第一问怎么求最长不降子序列.设f[i]f[i]f[i ...

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

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

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

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

随机推荐

  1. C++ 嵌套类使用(二)

    C++嵌套类 1.   嵌套类的名字只在外围类可见. 2.   类的私有成员只有类的成员和友元可以访问,因此外围类不可以访问嵌套类的私有成员.嵌套类可以访问外围类的成员(通过对象.指针或者引用). 3 ...

  2. C++开发必看 四种强制类型转换的总结

    C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是: TYPE b = (TYPE)a C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用. const_cast ...

  3. eCos中的线程与同步

    http://blog.csdn.net/ooaven/article/details/6280018 先看一下eCos线程的创建.控制以及优先级的操作这三个方面的知识,主要是对它的实现方式及API做 ...

  4. 再探Tomcat

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAmQAAADyCAIAAABs006cAAAgAElEQVR4nO2d228b1RaH+2/l9RQhQE

  5. windows命令行编码与nodejs编码格式冲突的解决方式

    今天写一个工具,由于大部分人使用的机器都是windows,在和nodejs结合的时候出问题了. win命令行的编码格式是gbk,而nodejs支持的编码只有:utf8 ascii和base64,必须让 ...

  6. GCC编译警告和错误

    1 error: expected expression before 'else' else之前无表达式. 2 error: lvalue required as left operand of a ...

  7. WCF实例上下文

    实例上下文模式(IntanceContext Mode)表示服务端的服务实例与客户端的服务代理的绑定方式. 在WCF中有三种不同的实例上下文模式,单调(Per-Call)模式,会话(Per-Sessi ...

  8. node.js模块值formidable

    模块地址:https://github.com/felixge/node-formidable var formidable = require('formidable'), http = requi ...

  9. [原]数据库中的partitioning和sharding

    1. 如何理解定义 在中文中,partitioning和sharding都有分区的意思.从大的方面来说,这两个词所执行的动作确实也和分区相关.partitioning在很多场合是vertical pa ...

  10. raid之理解

    RAID方案有两种,一种是硬件RAID解决方案,一种是软RAID解决方案. 硬件RAID解决方案 1.RAID 0 RAID 0是最早出现的RAID模式,即Data Stripping数据分条技术.R ...