BZOJ2244: [SDOI2011]拦截导弹

2244: [SDOI2011]拦截导弹

Time Limit: 30 Sec  Memory Limit: 512 MBSec  Special Judge
Submit: 954  Solved: 333
[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。

思路{

  三维偏序裸题啊。

  考场上没时间写了。。。。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
",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;
}
原文地址:https://www.cnblogs.com/zzmmm/p/8052933.html