zoukankan      html  css  js  c++  java
  • [BZOJ2244][SDOI2011]拦截导弹 CDQ分治

    2244: [SDOI2011]拦截导弹

    Time Limit: 30 Sec  Memory Limit: 512 MB  Special Judge

    Description

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

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

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

    Input

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

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

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

     

    Output

    输出包含两行。

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

    第二行包含n个0到1之间的实数,第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。
     

    题解:

    我们分析一下这道题,其实他分为两个子任务,

    一个是计算最长的三维偏序的不下降子序列,

    一个是计算每枚导弹在所有可能的方案中出现了多少次.

    首先我们离散一下,方便处理.

    接着我们考虑,对于导弹i,他处在的导弹序列首先他自己一定在里面,其次序列一定是前面一段后面一段(废话.....)

    这样总的方案数就应该是前面一段的方案数*后面一段的方案数.

    那么我们考虑类似最短路计数问题的处理方法,我们处理一个类似的f数组,f[0]表示以i开始/f[1]表示以i结束的最长子序列长度

    同时统计一个g数组,g[0]表示以i开始/g[0]表示以i结束的最长子序列方案数,在CDQ转移的时候如果长度相等累加,长度不等就覆盖上去

    这两个数组正反两遍CDQ就可以计算得到

    这样,按照上面的计算方式,总的方案数就应该是g[0][i]*g[1][i].

    那么如果某个导弹处在最长子序列中,一定会有f[0][i]+f[1][i]-1==maxlength(-1是因为要把自己减去,不能算两遍)

    设总方案数为sum,那么这枚导弹出现的概率就是g[0][i]*g[1][i]/sum

    这样我们统计一下上述数组并计算答案即可.

    (我偷了下懒,把序列反转之后数值取了下反,就可以不写两遍CDQ,调用同一个函数就行了233)

    代码实现:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <iostream>
      5 using namespace std;
      6 const int N=50010;
      7 int n,toth,totv,st[N],top,f[2][N];
      8 struct node
      9 {
     10     int h,v,tim;
     11     inline void read(){scanf("%d%d",&h,&v);}
     12 }m[N];
     13 inline bool mt1(const node &a,const node &b)
     14 {
     15     if(a.v==b.v&&a.h==b.h)return a.tim<b.tim;
     16     return a.h==b.h?a.v<b.v:a.h<b.h;
     17 }
     18 inline bool mt2(const node &a,const node &b)
     19     {return a.tim<b.tim;}
     20 int bit[N];
     21 double cnt[N],g[2][N],ans[N];
     22 inline int lowbit(int a){return a&-a;}
     23 inline void add(int a,int b,double c)
     24 {
     25     while(a<=totv)
     26     {
     27         if(bit[a]<b)bit[a]=b,cnt[a]=c;
     28         else if(bit[a]==b)cnt[a]+=c;
     29         a+=lowbit(a);
     30     }
     31 }
     32 inline void query(int a,int &b,double &c)
     33 {
     34     b=0,c=0.0;
     35     while(a)
     36     {
     37         if(bit[a]>b)b=bit[a],c=cnt[a];
     38         else if(bit[a]==b)c+=cnt[a];
     39         a-=lowbit(a);
     40     }
     41 }
     42 inline void clear(int a)
     43 {
     44     while(a<=totv)
     45     {
     46         if(!bit[a])return;
     47         bit[a]=0,cnt[a]=0.0,a+=lowbit(a);
     48     }
     49 }
     50 inline void CDQ(int l,int r,int o)
     51 {
     52     if(l==r)return;
     53     register int i,mi=l+r>>1;
     54     CDQ(l,mi,o);
     55     sort(m+l,m+r+1,mt1);
     56     int x=0;double u=0.0;
     57     for(i=l;i<=r;++i)
     58     {
     59         if(m[i].tim<=mi)
     60             add(m[i].v,f[o][m[i].tim],g[o][m[i].tim]);
     61         else 
     62         {
     63             query(m[i].v,x,u);
     64             if(x+1>f[o][m[i].tim])
     65                 f[o][m[i].tim]=x+1,g[o][m[i].tim]=u;
     66             else if(x+1==f[o][m[i].tim])
     67                 g[o][m[i].tim]+=u;
     68         }
     69     }
     70     for(i=l;i<=r;++i)
     71         if(m[i].tim<=mi)clear(m[i].v);
     72     sort(m+l,m+r+1,mt2);
     73     CDQ(mi+1,r,o);
     74 }
     75 inline void intn()
     76 {
     77     register int i;
     78     for(i=1;i<=n;++i)st[i]=m[i].h;
     79     sort(st+1,st+n+1),toth=unique(st+1,st+n+1)-st-1;
     80     for(i=1;i<=n;++i)
     81         m[i].h=lower_bound(st+1,st+toth+1,m[i].h)-st;
     82     for(i=1;i<=n;++i)st[i]=m[i].v;
     83     sort(st+1,st+n+1),totv=unique(st+1,st+n+1)-st-1;
     84     for(i=1;i<=n;++i)
     85         m[i].v=lower_bound(st+1,st+totv+1,m[i].v)-st;
     86 }
     87 int main()
     88 {
     89     register int i,j;scanf("%d",&n);
     90     for(i=n;i;--i)m[i].read();
     91     intn();
     92     for(i=1;i<=n;++i)
     93         m[i].tim=i,f[0][i]=f[1][i]=g[0][i]=g[1][i]=1;
     94     CDQ(1,n,0);
     95     reverse(m+1,m+n+1);
     96     for(i=1;i<=n;++i)
     97         m[i].tim=i,m[i].h=toth-m[i].h+1,m[i].v=totv-m[i].v+1;
     98     CDQ(1,n,1);
     99     int maxn=0;double sum=0;
    100     for(i=1;i<=n;++i)
    101     {
    102         if(maxn<f[0][i])maxn=f[0][i],sum=g[0][i];
    103         else if(f[0][i]==maxn)sum+=g[0][i];
    104     }
    105     printf("%d
    ",maxn);
    106     for(i=1;i<=n;++i)
    107     {
    108         if(f[0][n-i+1]+f[1][i]-1==maxn)
    109             ans[i]=g[0][n-i+1]*g[1][i]/sum;
    110         else ans[i]=0.0;
    111     }
    112     for(i=1;i<n;++i)printf("%.5lf ",ans[i]);
    113     printf("%.5lf",ans[n]);
    114 }

     

     

  • 相关阅读:
    border-radius:50%和100%究竟有什么区别
    GoLang几种读文件方式的比较
    Golang Import使用入门
    golang: 常用数据类型底层结构分析
    Python--字典操作
    Python--字符串操作
    Python split 分割中文
    LR(逻辑回归)
    Python--列表操作
    Eclipse 使用Anaconda python 解释器
  • 原文地址:https://www.cnblogs.com/LadyLex/p/7617459.html
Copyright © 2011-2022 走看看