• BZOJ2244: [SDOI2011]拦截导弹(CDQ分治,二维LIS,计数)


    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

    解题思路:

    让我想起了前一阵学弟们做的题(手动滑稽)

    这道题第一问相当于一个二维LIS。

    主要是第二问,我们只需统计有多少最大的答案,和节点在多少方案中,最后相除即可。

    最长的只需枚举统计就好了。

    而节点在多少方案中可以统计其最长前缀LIS和最长后缀LIS,如果相加等于答案+1那么就合法。

    相当于最长前缀LIS数量*最长后缀LIS数量。

    这个可以用结构体重载运算符实现。

    最后中间运算变量可能>1020中间变量要用double,因为double不会爆而是牺牲精度。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define lll spc<<1
      5 #define rrr spc<<1|1
      6 const int N=200000;
      7 const int M=1000000;
      8 struct trnt{
      9     int maxv;
     10     double maxt;
     11 }tr[M],strnt;
     12 struct data{
     13     int t;
     14     int h;
     15     int tv;
     16     int v;
     17 }d[N];
     18 int n;
     19 int tot;
     20 int cnt;
     21 double sum;
     22 trnt f[N],g[N];
     23 bool cmpb(data a,data b){return a.t<b.t;}
     24 bool cmph(data a,data b){return a.h>b.h;}
     25 bool cmpv(data a,data b){return a.tv<b.tv;}
     26 trnt max(trnt x,trnt y)
     27 {
     28     trnt ans;
     29     if(x.maxv<y.maxv)
     30         ans=y;
     31     else if(x.maxv>y.maxv)
     32         ans=x;
     33     else
     34         ans=(trnt){x.maxv,x.maxt+y.maxt};
     35     return ans;
     36 }
     37 void pushup(int spc)
     38 {
     39     tr[spc]=max(tr[lll],tr[rrr]);
     40     return ;
     41 }
     42 void update(int l,int r,int pos,int spc,int v,double t)
     43 {
     44     if(l==r)
     45     {
     46         if(v==-1)
     47             tr[spc]=strnt;
     48         else{
     49             if(tr[spc].maxv<v)
     50                 tr[spc]=(trnt){v,t};
     51             else if(tr[spc].maxv==v)
     52                 tr[spc].maxt+=t;
     53         }
     54         return ;
     55     }
     56     int mid=(l+r)>>1;
     57     if(pos<=mid)
     58         update(l,mid,pos,lll,v,t);
     59     else
     60         update(mid+1,r,pos,rrr,v,t);
     61     pushup(spc);
     62     return ;
     63 }
     64 trnt query(int ll,int rr,int l,int r,int spc)
     65 {
     66     if(ll>r||l>rr)
     67         return strnt;
     68     if(ll<=l&&r<=rr)
     69         return tr[spc];
     70     int mid=(l+r)>>1;
     71     return max(query(ll,rr,l,mid,lll),query(ll,rr,mid+1,r,rrr));
     72 }
     73 void CDQ(int l,int r)
     74 {
     75     if(l==r)
     76         return ;
     77     int mid=(l+r)>>1;
     78     CDQ(l,mid);
     79     std::sort(d+l,d+mid+1,cmph);
     80     std::sort(d+mid+1,d+r+1,cmph);
     81     int j=l;
     82     for(int i=mid+1;i<=r;i++)
     83     {
     84         for(;j<=mid&&d[j].h>=d[i].h;j++)
     85             update(1,n,d[j].v,1,f[d[j].t].maxv,f[d[j].t].maxt);
     86         trnt tmp=query(d[i].v,n,1,n,1);
     87         tmp.maxv++;
     88         f[d[i].t]=max(f[d[i].t],tmp);
     89     }
     90     for(int i=l;i<j;i++)
     91         update(1,n,d[i].v,1,-1,0);
     92     std::sort(d+mid+1,d+r+1,cmpb);
     93     CDQ(mid+1,r);
     94     return ;
     95 }
     96 void Dark_CDQ(int l,int r)
     97 {
     98     if(l==r)
     99         return ;
    100     int mid=(l+r)>>1;
    101     Dark_CDQ(mid+1,r);
    102     std::sort(d+l,d+mid+1,cmph);
    103     std::sort(d+mid+1,d+r+1,cmph);
    104     int j=r;
    105     for(int i=mid;i>=l;i--)
    106     {
    107         for(;j>=mid+1&&d[j].h<=d[i].h;j--)
    108             update(1,n,d[j].v,1,g[d[j].t].maxv,g[d[j].t].maxt);
    109         trnt tmp=query(1,d[i].v,1,n,1);
    110         tmp.maxv++;
    111         g[d[i].t]=max(g[d[i].t],tmp);
    112     }
    113     for(int i=r;i>j;i--)
    114         update(1,n,d[i].v,1,-1,0);
    115     std::sort(d+l,d+mid+1,cmpb);
    116     Dark_CDQ(l,mid);
    117     return ;
    118 }
    119 int main()
    120 {
    121     scanf("%d",&n);
    122     for(int i=1;i<=n;i++)
    123     {
    124         scanf("%d%d",&d[i].h,&d[i].tv);
    125         d[i].t=i;
    126     }
    127     std::sort(d+1,d+n+1,cmpv);
    128     tot++;
    129     d[1].v=1;
    130     for(int i=2;i<=n;i++)
    131     {
    132         if(d[i].tv!=d[i-1].tv)
    133             tot++;
    134         d[i].v=tot;
    135     }
    136     std::sort(d+1,d+n+1,cmpb);
    137     for(int i=1;i<=n;i++)
    138         f[i]=g[i]=(trnt){1,1};
    139     CDQ(1,n);
    140     trnt ans=strnt;
    141     for(int i=1;i<=n;i++)
    142         ans=max(ans,f[i]);
    143     printf("%d
    ",ans.maxv);
    144     for(int i=1;i<=n;i++)
    145         if(f[i].maxv==ans.maxv)
    146             sum+=(double)(f[i].maxt);
    147     std::sort(d+1,d+n+1,cmpb);
    148     Dark_CDQ(1,n);
    149     std::sort(d+1,d+n+1,cmpb);
    150     for(int i=1;i<=n;i++)
    151     {
    152         if(g[i].maxv+f[i].maxv-1==ans.maxv)
    153             printf("%.5lf ",(double)(f[i].maxt)*(double)(g[i].maxt)/sum);
    154         else
    155             printf("0.00000 ");
    156     }
    157     puts("");
    158     return 0;
    159 }
  • 相关阅读:
    使用 HttpClient 调用第三方接口
    Servlet 的生命周期及工作原理
    SpringBoot 框架简介及搭建
    使用 SimpleDateFormat 获取上个月的日期
    LoadRunner常见问题(一)
    Web_reg_find()函数的使用
    IEtester调试IE6,IE7,IE8,IE9的CSS兼容性的免费工具
    web_find()函数检查中文字符串失败的处理方法
    lr_shoami()的用法
    IP欺骗经验总结
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10115723.html
Copyright © 2020-2023  润新知