现在的位置: 首页 > 综合 > 正文

拦截导弹(missile)

2018年04月26日 ⁄ 综合 ⁄ 共 6780字 ⁄ 字号 评论关闭

拦截导弹
【问题描述】
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:
虽然它的第一发炮弹能够到达任意的高度、并且能够拦截任意速度的导弹,但是以后每一发炮弹都
不能高于前一发的高度,其拦截的导弹的飞行速度也不能大于前一发。某天,雷达捕捉到敌国的导
弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
在不能拦截所有的导弹的情况下,我们当然要选择使国家损失最小、也就是拦截导弹的数量最
多的方案。但是拦截导弹数量的最多的方案有可能有多个,如果有多个最优方案,那么我们会随机
选取一个作为最终的拦截导弹行动蓝图。
我方间谍已经获取了所有敌军导弹的高度和速度,你的任务是计算出在执行上述决策时,每枚
导弹被拦截掉的概率。
【输入格式】
第一行包含一个正整数,表示敌军导弹数量;
下面行按顺序给出了敌军所有导弹信息:
第行包含个正整数和,分别表示第枚导弹的高度和速度。
【输出格式】
输出包含两行。
第一行为一个正整数,表示最多能拦截掉的导弹数量;
第二行包含个0 到1 之间的实数,第个数字表示第枚导弹被拦截掉的概率(你可以保留任
意多位有效数字)。
【样例输入】

4

3 30
4 40
6 60
3 30
【样例输出】
2
0.33333 0.33333 0.33333 1.00000
【数据规模和约定】

n<=50000

1<=h,v<=10^9

线段树套线段树

设f[i]为打到这一颗导弹的最长长度

按导弹的顺序扫描,f[i]的取值则为线段树套线段树中满足条件的最大值+1

这样便可以求出来最大值

求出f数组之后,把导弹按f[i]为第一关键字,i为第二关键字排序

用pro[i]表示取了该值之后右边的方案数有多少

按f的取值分阶段扫描,每扫描到一个i,将上一阶段所有大于i的导弹的方案数插入线段树

本阶段扫描完成,将上阶段的导弹全部删除,我采取了插入负数的方式

再用ble[i]表示取了该值左边的方案数有多少种,求的方法类似其pro的方法

每个导弹被打过的概率为(pre[i]*ble[i]/总方案数)

这里对精度要求并不高,而且方案数可能会爆int64,所以采用了extended来存储pre和ble

这个h和v的取值为[1,10^9],我本认为(log(10^9))^2跟(log(10^5))^2差的不是很多,虽然确实差的不算多900跟256的差别……

但线段树不离散化会超时还要爆内存,所以加入离散化

写了9个k

program missile;
var
  w,o,s,e,ans,all,tot,n,i,j,k:longint;
  sa:extended;
  quick,new:array [0..100001] of longint;
  ble,pro:array [0..50001] of extended;
  dl,v,h,f:array [0..50001] of longint;
  left,right,root:array [0..1000001] of longint;
  lef,rig,point:array [0..10000001] of longint;
  sum:array [0..10000001] of extended;

procedure swap (var a,b:longint);inline;
var
  i:longint;
begin
  i:=a;
  a:=b;
  b:=i;
end;

procedure insert1(vi,p,l,r,now:longint;o:extended);
var
  mid:longint;
begin
  sum[now]:=sum[now]+o;
  if point[now]<p then point[now]:=p;
  if l=r then exit;
  mid:=(l+r) div 2;
  if vi<=mid then
    begin
      if lef[now]=0 then
        begin
          inc(all);
          lef[now]:=all;
        end;
      insert1(vi,p,l,mid,lef[now],o);
    end
                    else
    begin
      if rig[now]=0 then
        begin
          inc(all);
          rig[now]:=all;
        end;
      insert1(vi,p,mid+1,r,rig[now],o);
    end;
end;

procedure insert (hi,vi,p,l,r,now:longint;o:extended);
var
  mid:longint;
begin
  if root[now]=0 then
    begin
      inc(all);
      root[now]:=all;
    end;
  insert1(vi,p,1,w+1,root[now],o);
  if l=r then exit;
  mid:=(l+r) div 2;
  if hi<=mid then
    begin
      if left[now]=0 then
        begin
          inc(tot);
          left[now]:=tot;
        end;
      insert(hi,vi,p,l,mid,left[now],o);
    end
             else
    begin
      if right[now]=0 then
        begin
          inc(tot);
          right[now]:=tot;
        end;
      insert(hi,vi,p,mid+1,r,right[now],o);
    end;
end;

function find1 (vi,l,r,now:longint):longint;
var
  ans,k,mid:longint;
begin
  if vi=l then exit(point[now]);
  mid:=(l+r) div 2;
  if vi>mid then
    if rig[now]=0 then exit(0)
                  else exit(find1(vi,mid+1,r,rig[now]))
            else
    begin
      ans:=0;
      if lef[now]=0 then k:=0
                    else k:=find1(vi,l,mid,lef[now]);
      if ans<k then ans:=k;
      if rig[now]=0 then k:=0
                    else k:=find1(mid+1,mid+1,r,rig[now]);
      if k>ans then ans:=k;
      exit(ans);
    end;
end;

function find(hi,vi,l,r,now:longint):longint;
var
  ans,k,mid:longint;
begin
  if hi=l then
    if root[now]=0 then exit(0)
                   else exit(find1(vi,1,w+1,root[now]));
  mid:=(l+r) div 2;
  if hi>mid then
    if right[now]=0 then exit(0)
                    else exit(find(hi,vi,mid+1,r,right[now]))
            else
    begin
      ans:=0;
      if left[now]=0 then k:=0
                     else k:=find(hi,vi,l,mid,left[now]);
      if k>ans then ans:=k;
      if right[now]=0 then k:=0
                      else k:=find(mid+1,vi,mid+1,r,right[now]);
      if k>ans then ans:=k;
      exit(ans);
    end;
end;

function solve1 (vi,l,r,now:longint):extended;
var
  mid:longint;
  ans:extended;
begin
  if vi=r then exit(sum[now]);
  mid:=(l+r) div 2;
  if vi<=mid then
    if lef[now]=0 then exit(0)
                  else exit(solve1(vi,l,mid,lef[now]))
             else
    begin
      ans:=0;
      if lef[now]<>0 then ans:=ans+solve1(mid,l,mid,lef[now]);
      if rig[now]<>0 then ans:=ans+solve1(vi,mid+1,r,rig[now]);
      exit(ans);
    end;
end;

function solve (hi,vi,l,r,now:longint):extended;
var
  mid:longint;
  ans:extended;
begin
  if r=hi then
    if root[now]=0 then exit(0)
                   else exit(solve1(vi,1,w+1,root[now]));
  mid:=(l+r) div 2;
  if hi<=mid then
    if left[now]=0 then exit(0)
                   else exit(solve(hi,vi,l,mid,left[now]))
             else
    begin
      ans:=0;
      if left[now]<>0 then ans:=ans+solve(mid,vi,l,mid,left[now]);
      if right[now]<>0 then ans:=ans+solve(hi,vi,mid+1,r,right[now]);
      exit(ans);
    end;
end;

function doit1 (vi,l,r,now:longint):extended;
var
  mid:longint;
  ans:extended;
begin
  if l=vi then exit(sum[now]);
  mid:=(l+r) div 2;
  if vi>mid then
    if rig[now]=0 then exit(0)
                  else exit(doit1(vi,mid+1,r,rig[now]))
           else
    begin
      ans:=0;
      if lef[now]<>0 then ans:=ans+doit1(vi,l,mid,lef[now]);
      if rig[now]<>0 then ans:=ans+doit1(mid+1,mid+1,r,rig[now]);
      exit(ans);
    end;
end;

function doit (hi,vi,l,r,now:longint):extended;
var
  mid:longint;
  ans:extended;
begin
  if l=hi then
    if root[now]=0 then exit(0)
                   else exit(doit1(vi,1,w+1,root[now]));
  mid:=(l+r) div 2;
  if hi>mid then
    if right[now]=0 then exit(0)
                    else exit(doit(hi,vi,mid+1,r,right[now]))
            else
    begin
      ans:=0;
      if left[now]<>0 then ans:=ans+doit(hi,vi,l,mid,left[now]);
      if right[now]<>0 then ans:=ans+doit(mid+1,vi,mid+1,r,right[now]);
      exit(ans);
    end;
end;

procedure qsort (s,e:longint);
var
  i,j,k:longint;
begin
  if s>=e then exit;
  i:=s;
  j:=e;
  k:=dl[(s+e) div 2];
  while i<=j do
    begin
      while (f[dl[i]]<f[k])or((f[dl[i]]=f[k])and(dl[i]<k)) do inc(i);
      while (f[dl[j]]>f[k])or((f[dl[j]]=f[k])and(dl[j]>k)) do dec(j);
      if i>j then break;
      swap(dl[i],dl[j]);
      inc(i);
      dec(j);
    end;
  qsort(s,j);
  qsort(i,e);
end;

procedure qsort1 (s,e:longint);
var
  i,j,k:longint;
begin
  if s>=e then exit;
  i:=s;
  j:=e;
  k:=quick[(s+e) div 2];
  while i<=j do
    begin
      while quick[i]<k do inc(i);
      while quick[j]>k do dec(j);
      if i>j then break;
      swap(quick[i],quick[j]);
      inc(i);
      dec(j);
    end;
  qsort1(s,j);
  qsort1(i,e);
end;

function convert (now:longint):longint;inline;
var
  s,e,mid:longint;
begin
  s:=1;
  e:=w;
  while s<>e do
    begin
      mid:=(s+e) div 2;
      if new[mid]=now then exit(mid)
                      else
      if new[mid]>now then e:=mid-1
                      else s:=mid+1;
    end;
  exit(s);
end;

begin
  assign(input,'missile.in');
  reset(input);
  assign(output,'missile.out');
  rewrite(output);
  read(n);
  for i:=1 to n do
    begin
      read(h[i],v[i]);
      quick[2*i-1]:=h[i];
      quick[2*i]:=v[i];
    end;
  qsort1(1,2*n);
  w:=0;
  i:=1;
  while i<=2*n do
    begin
      k:=i;
      while quick[i]=quick[k] do inc(i);
      inc(w);
      new[w]:=quick[k];
    end;
  for i:=1 to n do
    begin
      h[i]:=convert(h[i]);
      v[i]:=convert(v[i]);
    end;
  ans:=1;
  for i:=1 to n do
    begin
      f[i]:=find(h[i],v[i],1,w+1,0)+1;
      insert(h[i],v[i],f[i],1,w+1,0,0);
      if f[i]>ans then ans:=f[i];
      dl[i]:=i;
    end;
  writeln(ans);
  tot:=0;
  all:=0;
  fillchar(left,sizeof(left),0);
  fillchar(right,sizeof(right),0);
  fillchar(lef,sizeof(lef),0);
  fillchar(rig,sizeof(rig),0);
  fillchar(root,sizeof(root),0);
  qsort(1,n);
  h[n+1]:=1;
  v[n+1]:=1;
  f[n+1]:=ans+1;
  pro[n+1]:=1;
  h[0]:=w+1;
  v[0]:=w+1;
  f[0]:=0;
  dl[n+1]:=n+1;
  s:=n+1;
  e:=n+1;
  i:=n;
  while i>=0 do
    begin
      k:=i;
      j:=e;
      while (i>=0)and(f[dl[i]]=f[dl[k]]) do
        begin
          while (j>=s)and(dl[j]>dl[i]) do
            begin
              insert(h[dl[j]],v[dl[j]],-1,1,w+1,0,pro[dl[j]]);
              dec(j);
            end;
          pro[dl[i]]:=solve(h[dl[i]],v[dl[i]],1,w+1,0);
          dec(i);
        end;
      for o:=j+1 to e do
        insert(h[dl[o]],v[dl[o]],-1,1,w+1,0,-pro[dl[o]]);
      e:=s-1;
      s:=i+1;
    end;
  tot:=0;
  all:=0;
  fillchar(left,sizeof(left),0);
  fillchar(right,sizeof(right),0);
  fillchar(lef,sizeof(lef),0);
  fillchar(rig,sizeof(rig),0);
  fillchar(root,sizeof(root),0);
  fillchar(sum,sizeof(sum),0);
  s:=0;
  e:=0;
  ble[0]:=1;
  i:=1;
  while i<=n+1 do
    begin
      k:=i;
      j:=s;
      while (i<=n+1)and(f[dl[i]]=f[dl[k]]) do
        begin
          while (j<=e)and(dl[j]<dl[i]) do
            begin
              if pro[dl[j]]>0.1 then
                insert(h[dl[j]],v[dl[j]],-1,1,w+1,0,ble[dl[j]]);
              inc(j);
            end;
          if pro[dl[i]]>0.1 then
            ble[dl[i]]:=doit(h[dl[i]],v[dl[i]],1,w+1,0);
          inc(i);
        end;
      for o:=s to j-1 do
        if pro[dl[o]]>0.1 then
          insert(h[dl[o]],v[dl[o]],-1,1,w+1,0,-ble[dl[o]]);
      s:=e+1;
      e:=i-1;
    end;
  for i:=1 to n do
    write(abs(pro[i]*ble[i]/pro[0]):0:5,' ');
  writeln;
  close(input);
  close(output);
end.
【上篇】
【下篇】

抱歉!评论已关闭.