bzoj 2244 [SDOI2011]拦截导弹

来源:互联网 发布:宁静长相 知乎 编辑:程序博客网 时间:2024/06/06 04:44

2244: [SDOI2011]拦截导弹

Time Limit: 30 Sec  Memory Limit: 512 MBSec  Special Judge
Submit: 662  Solved: 267
[Submit][Status][Discuss]

Description

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度、并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其拦截的导弹的飞行速度也不能大于前一发。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

在不能拦截所有的导弹的情况下,我们当然要选择使国家损失最小、也就是拦截导弹的数量最多的方案。但是拦截导弹数量的最多的方案有可能有多个,如果有多个最优方案,那么我们会随机选取一个作为最终的拦截导弹行动蓝图。

我方间谍已经获取了所有敌军导弹的高度和速度,你的任务是计算出在执行上述决策时,每枚导弹被拦截掉的概率。

Input

第一行包含一个正整数n,表示敌军导弹数量;

下面 行按顺序给出了敌军所有导弹信息:

i+1行包含2个正整数hivi,分别表示第 枚导弹的高度和速度。

Output

输出包含两行。

第一行为一个正整数,表示最多能拦截掉的导弹数量;

第二行包含n01之间的实数,第i个数字表示第i枚导弹被拦截掉的概率(你可以保留任意多位有效数字)。

Sample Input

4

3 30

4 40

6 60

3 30

Sample Output

2

0.33333 0.33333 0.33333 1.00000

【数据规模和约定】


对于100%的数据,1≤n≤5*104, 1≤hi ,vi≤109;

均匀分布着约30%的数据,所有vi均相等。

均匀分布着约50%的数据,满足1≤hi ,vi≤1000。

HINT

鸣谢kac提供sj程序!

Source

第一轮day2

[Submit][Status][Discuss]




【分析】

比较难搞的CDQ分治...因为个人智障等原因从早上10:30写到下午16:20...卧槽6个小时(虽然中间午休了一会)

曾经的导弹拦截只用求最长上升子序列,相当于二维偏序,本题加了一维,所以三维偏序,我们要用CDQ降一维。

把整个序列翻转后,考虑二维偏序的最长上升子序列如何求出。CDQ分治中三维分别为id,x,y,id为导弹的先后顺序,为方便我们将x,y都离散化掉。用a[i].f表示以导弹i为结尾的LIS长度,a[i].g表示以导弹i为结尾在LIS的条件下总共有几种方案。我们在处理区间(l,r)时,要先以id排序,处理区间(l,mid),处理完之后将(l,mid)和(mid+1,r)以x为关键字排序,设置两个指针,用树状数组更新答案,注意这里的树状数组有一些特殊的地方,详见代码。


那么导弹i为结尾的LIS都处理出来了,还要处理导弹i为开头的。事实上很简单,只要把序列翻转回来,x=n+1-x,y=n+1-y,就可以调用之前的函数统计答案了。

第二问的答案显然是一颗导弹所在的lis数/总的lis数。用g数组求解即可。


【代码】

//bzoj 2244#include<bits/stdc++.h>#define ll long long#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;const int mxn=50005;int n,m,t1,t2,T,kd;int h[mxn],s[mxn],tim[mxn],t_f[mxn];double t_g[mxn],ans[mxn];struct bullet{int id,x,y,f[2];double g[2];}a[mxn],tmp[mxn];inline bool comp(bullet u,bullet v) {if(u.x==v.x) return u.y<v.y;return u.x<v.x;}inline bool cmp(bullet u,bullet v) {return u.id<v.id;}inline int lowbit(int x) {return x&-x;}inline void add(int u,int f,double g){for(int i=u;i<=n;i+=lowbit(i)){    if(tim[i]!=T) tim[i]=T,t_f[i]=t_g[i]=0;    if(f>t_f[i]) t_f[i]=f,t_g[i]=g;     else if(f==t_f[i]) t_g[i]+=g;}}inline void getsum(int u,int &len,double &calc){len=0,calc=0.0;for(int i=u;i>=1;i-=lowbit(i))  if(tim[i]==T)  {    if(t_f[i]>len) len=t_f[i],calc=t_g[i];    else if(t_f[i]==len) calc+=t_g[i];  }}inline void CDQ(int l,int r){//if(l==5 && r==7 && kd==1)//{//puts("fuck");//}if(l==r){if(!a[l].f[kd]) a[l].f[kd]=a[l].g[kd]=1;return;}int i,j,mid=l+r>>1,l1=l,l2=mid+1;sort(a+l,a+r+1,cmp);CDQ(l,mid);T++;sort(a+mid+1,a+r+1,comp);for(l2=mid+1;l2<=r;l2++){for(l1;l1<=mid&&a[l1].x<=a[l2].x;l1++)  add(a[l1].y,a[l1].f[kd],a[l1].g[kd]);int mx;double sum;getsum(a[l2].y,mx,sum);if(mx>0){if(mx+1>a[l2].f[kd])  a[l2].f[kd]=mx+1,a[l2].g[kd]=sum;else if(mx+1==a[l2].f[kd])  a[l2].g[kd]+=sum;}}CDQ(mid+1,r);sort(a+l,a+r+1,comp);//fo(i,1,n) printf("test=%d\n",a[i].id);//puts("");}int main(){int i,j;scanf("%d",&n);for(i=n;i>=1;i--){scanf("%d%d",&a[i].x,&a[i].y);h[i]=a[i].x,s[i]=a[i].y,a[i].id=i;}sort(h+1,h+n+1),sort(s+1,s+n+1);t1=unique(h+1,h+n+1)-h-1;t2=unique(s+1,s+n+1)-s-1;fo(i,1,n) a[i].x=lower_bound(h+1,h+t1+1,a[i].x)-h;fo(i,1,n) a[i].y=lower_bound(s+1,s+t2+1,a[i].y)-s;kd=0,CDQ(1,n);sort(a+1,a+n+1,cmp);reverse(a+1,a+n+1);fo(i,1,n) a[i].x=n-a[i].x+1;fo(i,1,n) a[i].y=n-a[i].y+1;fo(i,1,n) a[i].id=i;kd=1,CDQ(1,n);//part one.int mxlen=0;double sum=0.0;fo(i,1,n)  if(a[i].f[0]>mxlen)    mxlen=a[i].f[0],sum=a[i].g[0];  else if(a[i].f[0]==mxlen)    sum+=a[i].g[0];//printf("test=%.5lf\n",sum);printf("%d\n",mxlen);fo(i,1,n) if(a[i].f[0]+a[i].f[1]-1==mxlen)  ans[a[i].id]=(a[i].g[0]*a[i].g[1])/sum;fo(i,1,n-1) printf("%.5lf ",ans[i]);printf("%.5lf\n",ans[n]);return 0;}/*72 53 62 52 43 51 96 3*/


原创粉丝点击