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 }
原文地址:https://www.cnblogs.com/blog-Dr-J/p/10115723.html