2244: [SDOI2011]拦截导弹
Time Limit: 30 Sec Memory Limit: 512 MBSec Special JudgeSubmit: 954 Solved: 333
[Submit][Status][Discuss]
Description
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度、并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其拦截的导弹的飞行速度也不能大于前一发。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
在不能拦截所有的导弹的情况下,我们当然要选择使国家损失最小、也就是拦截导弹的数量最多的方案。但是拦截导弹数量的最多的方案有可能有多个,如果有多个最优方案,那么我们会随机选取一个作为最终的拦截导弹行动蓝图。
我方间谍已经获取了所有敌军导弹的高度和速度,你的任务是计算出在执行上述决策时,每枚导弹被拦截掉的概率。
Input
第一行包含一个正整数n,表示敌军导弹数量;
下面行按顺序给出了敌军所有导弹信息:
第i+1行包含2个正整数hi和vi,分别表示第枚导弹的高度和速度。
Output
输出包含两行。
第一行为一个正整数,表示最多能拦截掉的导弹数量;
第二行包含n个0到1之间的实数,第i个数字表示第i枚导弹被拦截掉的概率(你可以保留任意多位有效数字)。
Sample Input
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。
思路{
三维偏序裸题啊。
考场上没时间写了。。。。QAQ
}
#include<bits/stdc++.h> #define ll long long #define RG register #define il inline #define N 50010 #define db double using namespace std; int n,now,sub[N],sz; struct dat{ int x,y,id; void read(int xx){scanf("%d%d",&x,&y);id=xx;} bool operator <(const dat & a)const{ return x==a.x?y<a.y:x<a.x; } }a[N]; bool comp(const dat & a,const dat & b){ return a.id<b.id; } bool comp1(const dat & a,const dat & b){ return a.x>b.x; } #define lowbit(x) ((x)&(-x)) struct node{ int f,col;db g; void clear(){f=g=col=0;} }tr[N]; typedef pair<int,db>pir; pir p[N],P[N]; void insert(int pos,int ff,db gg){ for(int i=pos;i<=n;i+=lowbit(i)){ if(tr[i].col!=now)tr[i].clear(),tr[i].col=now; if(tr[i].f==ff)tr[i].g+=gg; else if(tr[i].f>ff)return; else tr[i].f=ff,tr[i].g=gg; } } pir query(int pos){ int tempf(0);db tempg(0); for(int i=pos;i;i-=lowbit(i)){ if(tr[i].col!=now)continue; else{ if(tr[i].f>tempf)tempf=tr[i].f,tempg=tr[i].g; else if(tr[i].f==tempf)tempg+=tr[i].g; } } return make_pair(tempf,tempg); } pir max(pir a,pir b){ if(a.first==b.first){a.second+=b.second;return a;} if(a.first>b.first)return a; if(a.first<b.first)return b; } void solve(int l,int r,pir pp[]){ if(l==r){ if(!pp[a[l].id].first)pp[a[l].id]=make_pair(1,1); else pp[a[l].id].first++; return; } int mid=(l+r)>>1; solve(l,mid,pp); sort(a+l,a+mid+1,comp1),sort(a+mid+1,a+r+1,comp1); ++now;int n1(l); for(int i=mid+1;i<=r;++i){ while(a[n1].x>=a[i].x&&n1<=mid){ insert(sz-a[n1].y+1,pp[a[n1].id].first,pp[a[n1].id].second); n1++; } pp[a[i].id]=max(query(sz-a[i].y+1),pp[a[i].id]); } sort(a+mid+1,a+r+1,comp); solve(mid+1,r,pp); } void solve2(int l,int r,pir pp[]){ if(l==r){ if(!pp[a[l].id].first)pp[a[l].id]=make_pair(1,1); else pp[a[l].id].first++; return; } int mid=(l+r)>>1; solve2(mid+1,r,pp); sort(a+l,a+mid+1),sort(a+mid+1,a+r+1); ++now;int n1(mid+1); for(int i=l;i<=mid;++i){ while(a[n1].x<=a[i].x&&n1<=r){ insert(a[n1].y,pp[a[n1].id].first,pp[a[n1].id].second); n1++; } pp[a[i].id]=max(query(a[i].y),pp[a[i].id]); } sort(a+l,a+mid+1,comp); solve2(l,mid,pp); } int main(){ freopen("missile.in","r",stdin); freopen("missile.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;++i)a[i].read(i); for(int i=1;i<=n;++i)sub[i]=a[i].x; sort(sub+1,sub+n+1);sz=unique(sub+1,sub+n+1)-sub-1; for(int i=1;i<=n;++i)a[i].x=lower_bound(sub+1,sub+sz+1,a[i].x)-sub; for(int i=1;i<=n;++i)sub[i]=a[i].y; sort(sub+1,sub+n+1);sz=unique(sub+1,sub+n+1)-sub-1; for(int i=1;i<=n;++i)a[i].y=lower_bound(sub+1,sub+sz+1,a[i].y)-sub; solve(1,n,p); sort(a+1,a+n+1,comp); solve2(1,n,P);int temp(0);db ans(0); for(int i=1;i<=n;++i) temp=max(temp,p[i].first+P[i].first-1); printf("%d\n",temp); for(int i=1;i<=n;++i) if(p[i].first==temp){ ans+=p[i].second; } for(int i=1;i<=n;++i){ if(p[i].first+P[i].first-1==temp){ db Temp=p[i].second*P[i].second; printf("%.5lf ",Temp/ans); }else cout<<"0.00000 "; } return 0; }