【题目链接】

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. PHP程序员函数注释规格

    <?php/*** @name 名字* @abstract 申明变量/类/方法* @access 指明这个变量.类.函数/方法的存取权限* @author 函数作者的名字和邮箱地址* @cate ...

  2. 一个HexToInt的C/C++函数

    int  BetterVenca25(char* hex){   int res=0;   for(;*hex;hex++)   {  int d=toupper(*hex);      if(d & ...

  3. ***总结:在linux下连接redis并进行命令行操作(设置redis密码)

    [root@iZ254lfyd6nZ ~]# cd / [root@iZ254lfyd6nZ /]# ls bin boot dev etc home lib lib64 lost+found med ...

  4. HDU 2992 Hotel booking(BFS+DFS 或者 SPFA+Floyd)

    点我看题目 题意 : 一个司机要从1点到达n点,1点到n点中有一些点有宾馆,司机的最长开车时间不能超过10小时,所以要在10小时之内找到宾馆休息,但是为了尽快的走到n点,问最少可以经过几个宾馆. 思路 ...

  5. linux mysql数据库安装(tar.gz)

    概述 mysql数据库在linux下可以充分发挥威力,mysql数据库越来越受到软件公司的青睐,为什么呢? 免费.跨平台.轻.支持多并发 在北京很多软件公司属于创业型的中.小公司,从节约成本的角度考虑 ...

  6. ANDROID_MARS学习笔记_S01_003layout初步

    一.layout介绍 二.测试linear_layout1.activity_main.xml <?xml version="1.0" encoding="utf- ...

  7. nchar 和 nvarchar

    字符数据类型(nchar 长度固定,nvarchar 长度可变)和 Unicode 数据使用 UNICODE UCS-2 字符集. nchar [ ( n ) ] n 个字符的固定长度的 Unicod ...

  8. MyBatis的动态SQL操作--更新

    更新条件不确定,需要根据具体的情况生成sql语句. id是主键,一般不会去更新. 1.只更新name的值 update student set name = ? where id = ? 2.只更新s ...

  9. python-append()方法

    append() 方法向列表的尾部添加一个新的元素.只接受一个参数. >>> mylist = [1,2,3,4] >>> mylist [1, 2, 3, 4] ...

  10. MapReduce编程系列 — 3:数据去重

    1.项目名称: 2.程序代码: package com.dedup; import java.io.IOException; import org.apache.hadoop.conf.Configu ...