bzoj 2244: [SDOI2011]拦截导弹
来源:互联网 发布:网络教育的特征 编辑:程序博客网 时间:2024/06/13 01:33
题意
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度、并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其拦截的导弹的飞行速度也不能大于前一发。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
在不能拦截所有的导弹的情况下,我们当然要选择使国家损失最小、也就是拦截导弹的数量最多的方案。但是拦截导弹数量的最多的方案有可能有多个,如果有多个最优方案,那么我们会随机选取一个作为最终的拦截导弹行动蓝图。
我方间谍已经获取了所有敌军导弹的高度和速度,你的任务是计算出在执行上述决策时,每枚导弹被拦截掉的概率。
题解
很明显的一个CDQ分治DP。。
f[i]表示以他结尾的最多可以拦截多少个
这个用一个CDQ分治很快就可以算出来了
但是有多少种方案怎么弄呢?
其实我们可以在作CDQ的时候顺便弄出一个东西,就是这个答案优多少种方案
这个在树状数组上面加多一个辅助数组就可以了。。
然后经过他的怎么算呢?
我们可以倒着再做一个,求出后面开始,以他为开头的,其他一样,看做g[i]
如果一个导弹,
需要注意的地方:
1.在分治的时候,注意id的排序,因为我是分开的,前做左边,然后合并最后右边,所以会出现右边的id不顺序的情况
2.方案数乘积会爆
CODE:(调试都没有删。。)
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;typedef long double LD;const LL N=50005*2;LL n;struct qq{ LL h,v,id;}s[N],k[N];LD f[N],h[N];LD F[N],H[N];//对应的方案数 bool cmph (qq a,qq b){return a.h<b.h;}bool cmpv (qq a,qq b){return a.v<b.v;}bool cmpi (qq a,qq b){return a.id<b.id;}LD g[N],G[N];LL sta[N],top=0;void LSH(){ LL Last,Cnt; for (LL u=1;u<=n;u++) k[u]=s[u]; sort(k+1,k+1+n,cmph); Last=0;Cnt=0; for (LL u=n;u>=1;u--) { if (k[u].h!=Last) { Last=k[u].h; Cnt++; } s[k[u].id].h=Cnt; } for (LL u=1;u<=n;u++) k[u]=s[u]; sort(k+1,k+1+n,cmpv); Last=0;Cnt=0; for (LL u=n;u>=1;u--) { if (k[u].v!=Last) { Last=k[u].v; Cnt++; } s[k[u].id].v=Cnt; }}LL lb (LL x){return x&(-x);}LD shen;//个数 LL get (LL x){ LD lalal=0; while (x>=1) { if (g[x]>lalal) lalal=g[x],shen=0; if (g[x]==lalal) shen=shen+G[x]; x-=lb(x); } return lalal;}void change (LL x,LL y,LD z){ while (x<=n) { if (g[x]<y) g[x]=y,G[x]=0; if (g[x]==y) G[x]+=z; x+=lb(x); }}void reset (LL x)//这个位置清空 { while (x<=n) { g[x]=0;G[x]=0; x+=lb(x); }}void cdq (LL l,LL r){ if (l==r) return ;/* printf("OZY:%lld %lld\n",l,r); for (LL u=l;u<=r;u++) printf("%lld ",s[u].id); system("pause");*/ LL mid=(l+r)>>1; sort(s+l,s+r+1,cmpi); cdq(l,mid); sort(s+l,s+1+mid,cmph); sort(s+1+mid,s+r+1,cmph); LL now=l;// memset(g,0,sizeof(g));// memset(G,0,sizeof(G)); top=0; for (LL u=mid+1;u<=r;u++)//求解 { while (now<=mid&&s[now].h<=s[u].h) { sta[++top]=s[now].v; change(s[now].v,f[s[now].id],F[s[now].id]); now++; } shen=0; LL lalal=get(s[u].v)+1; if (f[s[u].id]<lalal) f[s[u].id]=lalal,F[s[u].id]=0; if (f[s[u].id]==lalal) F[s[u].id]+=shen; } for (LL u=1;u<=top;u++) reset(sta[u]); cdq(mid+1,r);/* for (LL u=1;u<=n;u++) printf("%lld ",f[u]); printf("\n");*/ return ;}void cdq1 (LL l,LL r){ if (l==r) return ;/* printf("OZY:%lld %lld\n",l,r); for (LL u=l;u<=r;u++) printf("%lld ",s[u].id); system("pause");*/ LL mid=(l+r)>>1; sort(s+l,s+r+1,cmpi); cdq1(mid+1,r); sort(s+l,s+1+mid,cmph);sort(s+1+mid,s+r+1,cmph); LL now=mid+1;// memset(g,0,sizeof(g));// memset(G,0,sizeof(G)); top=0; for (LL u=l;u<=mid;u++)//求解? { while (now<=r&&s[now].h<=s[u].h) { sta[++top]=s[now].v; change(s[now].v,h[s[now].id],H[s[now].id]); now++; } shen=0; LL lalal=get(s[u].v)+1; if (h[s[u].id]<lalal) h[s[u].id]=lalal,H[s[u].id]=0; if (h[s[u].id]==lalal) H[s[u].id]+=shen; } for (LL u=1;u<=top;u++) reset(sta[u]); cdq1(l,mid); return ;}int main(){ scanf("%lld",&n); for (LL u=1;u<=n;u++) { scanf("%lld%lld",&s[u].h,&s[u].v); s[u].id=u; f[u]=1;F[u]=1;H[u]=1;h[u]=1; } LSH(); sort(s+1,s+1+n,cmpi); cdq(1,n); LD ans=0; for (LL u=1;u<=n;u++) ans=max(ans,f[u]);/* for (LL u=1;u<=n;u++) { printf("%lld:%lld %lld\n",u,f[u],F[u]); } printf("\n");*/ printf("%.0Lf\n",ans); sort(s+1,s+1+n,cmpi); LSH(); sort(s+1,s+1+n,cmpi); cdq1(1,n); LD tot=0;//一共有多少种方案 for (LL u=1;u<=n;u++) if (f[u]==ans) tot=tot+F[u];// printf("%lld\n",tot); for (LL u=1;u<=n;u++) { if (f[u]+h[u]-1==ans) { printf("%.5Lf ",F[u]/tot*H[u]); } else printf("0.00000 "); }/* printf("\n"); printf("f:"); for (LL u=1;u<=n;u++) printf("%lld ",f[u]);/* printf("\nF:"); for (LL u=1;u<=n;u++) printf("%lld ",F[u]);*//* printf("\nh:"); for (LL u=1;u<=n;u++) printf("%lld ",h[u]);/* printf("\nH:"); for (LL u=1;u<=n;u++) printf("%lld ",H[u]);*/ return 0;}
阅读全文
0 1
- BZOJ 2244 [SDOI2011] 拦截导弹
- bzoj 2244 [SDOI2011]拦截导弹
- bzoj 2244: [SDOI2011]拦截导弹
- bzoj 2244: [SDOI2011]拦截导弹
- 【bzoj】2244: [SDOI2011]拦截导弹【cdq分治】
- [CDQ分治] BZOJ 2244 [SDOI2011]拦截导弹
- BZOJ 2244 SDOI2011 拦截导弹 CDQ分治/二维树状数组
- bzoj 2244: [SDOI2011]拦截导弹 (CDQ分治+DP)
- [BZOJ]2244: [SDOI2011]拦截导弹 DP+CDQ分治+树状数组
- 【SDOI2011】【BZOJ2244】拦截导弹
- 【bzoj2244】[SDOI2011]拦截导弹
- 【BZOJ2244】【SDOI2011】拦截导弹
- BZOJ2244 & Codevs1822 [SDOI2011]拦截导弹
- BZOJ 2244 拦截导弹 cdq分治
- [BZOJ2244][SDOI2011]拦截导弹(DP+CDQ分治)
- [BZOJ2244][SDOI2011]拦截导弹(dp+cdq分治)
- 拦截导弹
- 拦截导弹
- 关于Java面试,你应该准备这些知识点
- react-native 简天气——仅仅一个天气而已
- /与/* dispatcherservlet配置
- 谈谈单元测试之(二):测试工具 JUnit 3
- 最少拦截系统
- bzoj 2244: [SDOI2011]拦截导弹
- Windows7 64 bit 下解决:检索 COM 类工厂中 CLSID 为 {00024500-0000-0000-C000-000000000046} 的组件时失败
- oracle建表并主键自增
- 杭电acm P2025查找最大元素
- 安卓7.0打开相机(权限与内容提供器)
- 【创业】腾讯是如何成长为一家大公司的
- SRS 代码分析【保存AAC音频文件】
- LintCode 第175题 反转二叉树
- Spring REST API整理