bzoj 2244: [SDOI2011]拦截导弹
来源:互联网 发布:完美解码 mac版 编辑:程序博客网 时间:2024/06/06 10:02
题意:
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度、并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其拦截的导弹的飞行速度也不能大于前一发。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
在不能拦截所有的导弹的情况下,我们当然要选择使国家损失最小、也就是拦截导弹的数量最多的方案。但是拦截导弹数量的最多的方案有可能有多个,如果有多个最优方案,那么我们会随机选取一个作为最终的拦截导弹行动蓝图。
我方间谍已经获取了所有敌军导弹的高度和速度,你的任务是计算出在执行上述决策时,每枚导弹被拦截掉的概率。
题解:
容易发现,假如按最长上升子序列的思想,明显是三维偏序。注意这里要先分治左边,然后合并再分治右边。
然后如果想再算方案的话似乎就是四维偏序了,但其实只要求f的时候在树状数组中多存一个量,表方案数,就可以了。
code:
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;struct node{ int op,x,y,c;}q[50010],tmp[50010];int cnt=0;struct NODE {int h,v,num;}a[50010];int n,h[50010],v[50010],f[4][50010],Q[50010];double g[4][50010];struct trnode{ int max; double sum;}tr[50010];int lowbit(int x) {return x&-x;}void rechange(int k) {for(int i=k;i<=n;i+=lowbit(i)) tr[i].max=tr[i].sum=0;}void change(int k,int c,double s){ for(int i=k;i<=n;i+=lowbit(i)) { if(tr[i].max==c) tr[i].sum+=s; if(tr[i].max<c) tr[i].max=c,tr[i].sum=s; }}trnode get(int k){ trnode ans;ans.max=0;ans.sum=0; for(int i=k;i>=1;i-=lowbit(i)) { if(tr[i].max==ans.max) ans.sum+=tr[i].sum; if(ans.max<tr[i].max) ans=tr[i]; } return ans;}bool cmp_h(NODE a,NODE b) {return a.h<b.h;}bool cmp_v(NODE a,NODE b) {return a.v<b.v;}bool cmp1(node a,node b) {return a.x<b.x;}void cdq(int l,int r,int op){ if(l==r) return; int mid=(l+r)/2; cdq(l,mid,op); for(int i=mid+1;i<=r;i++) tmp[i]=q[i]; sort(tmp+mid+1,tmp+r+1,cmp1); int i=l,j=mid+1,st=0,len=0; while(i<=mid&&j<=r) { if(q[i].x<=tmp[j].x) change(q[i].y,f[op][q[i].c],g[op][q[i].c]),Q[++st]=q[i].y,i++; else { trnode ans=get(tmp[j].y); if(ans.max<f[op][tmp[j].c]-1) {j++;continue;} else if(ans.max==f[op][tmp[j].c]-1) g[op][tmp[j].c]+=ans.sum; else f[op][tmp[j].c]=ans.max+1,g[op][tmp[j].c]=ans.sum; j++; } } while(j<=r) { trnode ans=get(tmp[j].y); if(ans.max<f[op][tmp[j].c]-1) {j++;continue;} else if(ans.max==f[op][tmp[j].c]-1) g[op][tmp[j].c]+=ans.sum; else f[op][tmp[j].c]=ans.max+1,g[op][tmp[j].c]=ans.sum; j++; } for(i=1;i<=st;i++) rechange(Q[i]); cdq(mid+1,r,op); i=l;j=mid+1;len=0; while(i<=mid&&j<=r) { if(q[i].x<=q[j].x) tmp[++len]=q[i++]; else tmp[++len]=q[j++]; } while(i<=mid) tmp[++len]=q[i++]; while(j<=r) tmp[++len]=q[j++]; for(i=1;i<=len;i++) q[l+i-1]=tmp[i];}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d %d",&a[i].h,&a[i].v),a[i].num=i; for(int i=1;i<=n;i++) f[1][i]=f[2][i]=1,g[1][i]=g[2][i]=1; sort(a+1,a+n+1,cmp_h); int TMP=0; for(int i=1;i<=n;i++) { if(i==1||a[i].h!=a[i-1].h) TMP++; h[a[i].num]=TMP; } sort(a+1,a+n+1,cmp_v); TMP=0; for(int i=1;i<=n;i++) { if(i==1||a[i].v!=a[i-1].v) TMP++; v[a[i].num]=TMP; } for(int i=1;i<=n;i++) q[n-i+1].x=h[i],q[n-i+1].y=v[i],q[n-i+1].c=i; cdq(1,n,1); for(int i=1;i<=n;i++) q[i].x=n-h[i]+1,q[i].y=n-v[i]+1,q[i].c=i; cdq(1,n,2); int max=0;double sum=0; for(int i=1;i<=n;i++) { if(max==f[1][i]) sum+=g[1][i]; if(max<f[1][i]) max=f[1][i],sum=g[1][i]; } printf("%d\n",max); for(int i=1;i<=n;i++) { if(f[1][i]+f[2][i]-1!=max) printf("0.00000 "); else printf("%.5lf ",g[1][i]*g[2][i]/sum); }}
阅读全文
0 0
- 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分治)
- 拦截导弹
- 拦截导弹
- 奥迪把球形轮胎造出来了…...
- MYSQL
- 每天一个linux命令(19):find 命令概览
- Spring Cloud(八)高可用的分布式配置中心 Spring Cloud Config
- guava(一)
- bzoj 2244: [SDOI2011]拦截导弹
- redhat虚拟机配置网络
- 还在用虚拟机?是时候开始用Docker了
- 形参和实参的区别
- 关于Tomcat(8005,8080,8009)端口占用问题的一点总结配上网上找到的解决方法
- 实验_使用Struts框架进行数据验证(登陆校验)
- 多因子权重优化方法比较
- Fiori学习笔记
- 每天一个linux命令(20):find命令之exec