bzoj 2244 [SDOI2011]拦截导弹(DP+CDQ分治+BIT)
【题目链接】
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)的更多相关文章
- BZOJ 2244: [SDOI2011]拦截导弹 DP+CDQ分治
2244: [SDOI2011]拦截导弹 Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截 ...
- 【BZOJ2244】[SDOI2011]拦截导弹(CDQ分治)
[BZOJ2244][SDOI2011]拦截导弹(CDQ分治) 题面 BZOJ 洛谷 题解 不难发现这就是一个三维偏序+\(LIS\)这样一个\(dp\). 那么第一问很好求,直接\(CDQ\)分治之 ...
- bzoj 2244: [SDOI2011]拦截导弹 cdq分治
2244: [SDOI2011]拦截导弹 Time Limit: 30 Sec Memory Limit: 512 MBSec Special JudgeSubmit: 237 Solved: ...
- BZOJ - 2244 拦截导弹 (dp,CDQ分治+树状数组优化)
题目链接 dp进阶之CDQ分治优化dp. 前置技能:dp基本功底,CDQ分治,树状数组. 问题等价于求二维最长上升子序列,是一个三维偏序问题(时间也算一维). 设$dp[i]=(l,x)$为以第i枚导 ...
- BZOJ2244 [SDOI2011]拦截导弹 【cdq分治 + 树状数组】
题目 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其 ...
- bzoj 2244: [SDOI2011]拦截导弹
#include<cstdio> #include<iostream> #include<algorithm> #define M 100009 using nam ...
- BZOJ 2244: [SDOI2011]拦截导弹 (CDQ分治 三维偏序 DP)
题意 略- 分析 就是求最长不上升子序列,坐标取一下反就是求最长不下降子序列,比较大小是二维(h,v)(h,v)(h,v)的比较.我们不看概率,先看第一问怎么求最长不降子序列.设f[i]f[i]f[i ...
- bzoj 2244 [SDOI2011]拦截导弹(dp+CDQ+树状数组)
传送门 题解 看了半天完全没发现这东西和CDQ有什么关系…… 先把原序列翻转,求起来方便 然后把每一个位置表示成$(a,b,c)$其中$a$表示位置,$b$表示高度,$c$表示速度,求有多少个位置$a ...
- BZOJ 2244: [SDOI2011]拦截导弹 [CDQ分治 树状数组]
传送门 题意:三维最长不上升子序列以及每个元素出现在最长不上升子序列的概率 $1A$了好开心 首先需要从左右各求一遍,长度就是$F[0][i]+F[1][i]-1$,次数就是$G[0][i]*G[1] ...
随机推荐
- ./configure详解
'configure'脚本有大量的命令行选项.对不同的软件包来说,这些选项可能会有变化,但是许多基本的选项是不会改变的.带上'--help'选项执行'configure'脚本可以看到可用的所有选项.尽 ...
- 如何使用PHP实现一个WebService
WSDL WSDL(网络服务描述语言,Web Services Description Language)是一门基于 XML 的语言,用于描述 Web Services 以及如何对它们进行访问.这种文 ...
- Hardwood Species
http://poj.org/problem?id=2418 #include<cstdio> #include<cstring> #include<string> ...
- http://blog.csdn.net/xyang81/article/details/7292380
http://blog.csdn.net/xyang81/article/details/7292380
- POJ1753——Flip Game
Flip Game Description Flip game is played on a rectangular 4x4 field with two-sided pieces placed on ...
- Android EditText属性
1.EditText输入的文字为密码形式的设置 (1)通过.xml里设置: 把该EditText设为:android:password="true" // 以”.”形式显示文本 ( ...
- 主机头部分 www有和无是有区别的
关于主机部分www的问题: case 1: frontend web_service bind *:80 bind *:443 ssl crt /etc/haproxy/cert.pem acl ww ...
- 【HDOJ】2242 考研路茫茫——空调教室
tarjan缩点,然后树形dp一下可解.重点是重边的处理. /* 2242 */ #include <iostream> #include <sstream> #include ...
- poj1062
经典的图论建模题: 先拿开的等级问题不看: 每个物品本身的价格就是有一个自定义源点到这个点距离: 有了A物品B物品优惠为W就代表由B到A的有向路权值为W: 最后的最小花费就是源点的点1的最短路径(酋长 ...
- 【App FrameWork】页面之间的参数传递
若应用中有多个页面,这时2个页面之间可能需要进行参数传递.那么如何来实现呢? 首先想到的就是URL参数传递的方式,如:在panel里设置属性 data-defer="Pages/Shake. ...