[SDOI2011]拦截导弹

12分算法:

f[i]=max{f[j]}+1;(c[j]<c[i]&&a[j]<=a[i]&&b[j]<=b[i])(c代表时间)

g[i]代表以i为结尾的方案数,便有:g[i]=sigma{g[j]}(f[j]==f[i]-1)

但显然这样根本无法求出某一个在子序列中间的情况,

于是只可以n^2暴力更新第一问答案,期望得分12分。

40分算法:

用CDQ优化上面的DP,时间复杂度$ O(n*log2(n)) $,

于是便可以开心地拿到所有测试点第一问的分数。

85分算法:

我们设:

f1[i]代表以i为结尾的最大长度,g1[i]代表f1[i]的方案数,

f2[i]代表以i为开头的最大长度,g2[i]代表f2[i]的方案数。

之后便可以正反向跑一边CDQ,其实不用离散化,直接把树状数组的下标设为时间即可,但排序的时候一定要注意a,b一样的情况

树状数组在维护最大值的时候需要顺便维护最大值对应的方案数(原来树状数组可以这么干?!)

刚开始我用一个桶存储方案数概率一直超过1,问了cow mikufun之后才知道我的数组存的最大值中会有时间不满足题意的情况。

下面放上一段排序的代码(还有charm的)

bool comp_a1(fire x,fire y)
{
        if(x.a==y.a&&x.b==y.b) return x.c<y.c;
        if(x.a==y.a) return x.b>y.b;
        return x.a>y.a;
}
bool comp_b1(fire x,fire y)
{
        if(x.b==y.b&&x.a==y.a) return x.c<y.c;
        if(x.b==y.b) return x.a>y.a;
        return x.b>y.b;
}
bool comp_b2(fire x,fire y)
{
        if(x.b==y.b&&x.a==y.a) return x.c<y.c;
        if(x.b==y.b) return x.a<y.a;
        return x.b<y.b;
}
bool comp_a2(fire x,fire y)
{
        if(x.a==y.a&&x.b==y.b) return x.c<y.c;
        if(x.a==y.a) return x.b<y.b;
        return x.a<y.a;
}
Dybala
inline bool operator <(BOOM a,BOOM b){return a.h>b.h;}
charm

 


明显我的要复杂的多,但其实蛮好想的(主要不需要离散化),手玩一下样例就可以。

ans1=max{f1[i]};

设sum=sigma{g1[i]}(f1[i]==ans1)

于是每个导弹的概率便是:

g1[i]*g2[i]/sum (f1[i]+f2[i]-1==ans1)

0 (f1[i]+f2[i]-1!=ans1)

求解即可

100分算法:

方案数会爆long long所以用double或者__int128存储,

double类型会在数据非常大的时候舍弃一点精度来换取存储更大的数,

这个题精度1e-4就可以AC,所以double完全没问题。

 

void add(int x,int y,int z)

 

(啊啊啊函数调用double类型时时改成了long long爆了)

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<vector>
  7 #include<string>
  8 #include<cstring>
  9 #include<map>
 10 #define int long long
 11 #define max(a,b) (a>b?a:b)
 12 #define m(a) memset(a,0,sizeof(a))
 13 #define AA cout<<"Alita"<<endl
 14 using namespace std;
 15 const int N=5e4+10;
 16 int ans,n,c[N];
 17 double ge,p[N],sum,a[N];
 18 struct fire{int a,b,c,w1,w2;double g1,g2;}f[N];
 19 int lowbit(int x){return x&-x;}
 20 bool comp_a1(fire x,fire y)
 21 {
 22         if(x.a==y.a&&x.b==y.b) return x.c<y.c;
 23         if(x.a==y.a) return x.b>y.b;
 24         return x.a>y.a;
 25 }
 26 bool comp_b1(fire x,fire y)
 27 {
 28         if(x.b==y.b&&x.a==y.a) return x.c<y.c;
 29         if(x.b==y.b) return x.a>y.a;
 30         return x.b>y.b;
 31 }
 32 bool comp_b2(fire x,fire y)
 33 {
 34         if(x.b==y.b&&x.a==y.a) return x.c<y.c;
 35         if(x.b==y.b) return x.a<y.a;
 36         return x.b<y.b;
 37 }
 38 bool comp_a2(fire x,fire y)
 39 {
 40         if(x.a==y.a&&x.b==y.b) return x.c<y.c;
 41         if(x.a==y.a) return x.b<y.b;
 42         return x.a<y.a;
 43 }
 44 void add(int x,int y,double z)
 45 {
 46         while(x<=n)
 47         {
 48                 if(c[x]<y)
 49                 {
 50                         c[x]=y;
 51                         a[x]=z;
 52                 }
 53                 else if(c[x]==y)
 54                 {
 55                         a[x]+=z;
 56                 }
 57                 x+=lowbit(x);
 58         }
 59 }
 60 int get(int x)
 61 {
 62         int sum=0;
 63         ge=0;
 64         while(x)
 65         {
 66                 if(c[x]>sum)
 67                 {
 68                         sum=c[x];
 69                         ge=a[x];
 70                 }
 71                 else if(c[x]==sum)
 72                 {
 73                         ge+=a[x];
 74                 }
 75                 x-=lowbit(x);
 76         }
 77         return sum;
 78 }
 79 void clear(int x)
 80 {
 81         while(x<=n)
 82         {
 83                 c[x]=0;
 84                 a[x]=0;
 85                 x+=lowbit(x);
 86         }
 87 }
 88 void CDQ1(int l,int r)
 89 {
 90         if(l==r) return;
 91         int mid=(l+r)>>1,x=l,y=mid+1;
 92         CDQ1(l,mid);
 93         stable_sort(f+l,f+mid+1,comp_b1);
 94         stable_sort(f+mid+1,f+r+1,comp_b1);
 95         while(x<=mid&&y<=r)
 96         {
 97                 if(f[x].b>=f[y].b)
 98                 {
 99                         add(f[x].c,f[x].w1,f[x].g1);
100                         x++;
101                 }
102                 else
103                 {
104                         int sum=get(f[y].c)+1;
105                         if(f[y].w1<sum)
106                         {
107                                 f[y].w1=sum;
108                                 f[y].g1=ge;
109                         }
110                         else if(f[y].w1==sum&&sum!=1) f[y].g1+=ge;
111                         y++;
112                 }
113         }
114         while(y<=r)
115         {
116                 int sum=get(f[y].c)+1;
117                 if(f[y].w1<sum)
118                 {
119                         f[y].w1=sum;
120                         f[y].g1=ge;
121                 }
122                 else if(f[y].w1==sum&&sum!=1) f[y].g1+=ge;
123                 y++;
124         }
125         for(int i=l;i<x;i++)
126         {
127                 clear(f[i].c);
128         }
129         stable_sort(f+mid+1,f+r+1,comp_a1);
130         CDQ1(mid+1,r);
131 }
132 void CDQ2(int l,int r)
133 {
134         if(l==r) return;
135         int mid=(l+r)>>1,x=l,y=mid+1;
136         CDQ2(l,mid);
137         stable_sort(f+l,f+mid+1,comp_b2);
138         stable_sort(f+mid+1,f+r+1,comp_b2);
139         while(x<=mid&&y<=r)
140         {
141                 if(f[x].b<=f[y].b)
142                 {
143                         add(f[x].c,f[x].w2,f[x].g2);
144                         x++;
145                 }
146                 else
147                 {
148                         int sum=get(f[y].c)+1;
149                         if(f[y].w2<sum)
150                         {
151                                 f[y].w2=sum;
152                                 f[y].g2=ge;
153                         }
154                         else if(f[y].w2==sum&&sum!=1)
155                         {
156                                 f[y].g2+=ge;
157                         }
158                         y++;
159                 }
160         }
161         while(y<=r)
162         {
163                 int sum=get(f[y].c)+1;
164                 if(f[y].w2<sum)
165                 {
166                         f[y].w2=sum;
167                         f[y].g2=ge;
168                 }
169                 else if(f[y].w2==sum&&sum!=1)
170                 {
171                         f[y].g2+=ge;
172                 }
173                 y++;
174         }
175         for(int i=l;i<x;i++)
176         {
177                 clear(f[i].c);
178         }
179         stable_sort(f+mid+1,f+r+1,comp_a2);
180         CDQ2(mid+1,r);
181 }
182 signed main()
183 {
184         //freopen("1.in","r",stdin);
185         //freopen("1.out","w",stdout);
186         scanf("%lld",&n);
187         for(int i=1;i<=n;i++)
188         {
189                 f[i].c=i;
190                 scanf("%lld%lld",&f[i].a,&f[i].b);
191                 f[i].w1=1; f[i].w2=1;
192                 f[i].g1=1; f[i].g2=1;
193         }
194         stable_sort(f+1,f+n+1,comp_a1);
195         CDQ1(1,n);
196         for(int i=1;i<=n;i++) ans=max(ans,f[i].w1);
197         for(int i=1;i<=n;i++)
198         {
199                 if(f[i].w1==ans) sum+=f[i].g1;
200         }
201         for(int i=1;i<=n;i++) f[i].c=n-f[i].c+1;
202         stable_sort(f+1,f+n+1,comp_a2);
203         CDQ2(1,n);
204         for(int i=1;i<=n;i++)
205         {
206                 if(sum==0) continue;
207                 f[i].c=n-f[i].c+1;
208                 if(f[i].w1+f[i].w2-1==ans) p[f[i].c]=f[i].g1*f[i].g2/sum;
209         }
210         printf("%lld\n",ans);
211         for(int i=1;i<=n;i++) printf("%0.6lf ",p[i]);
212         return 0;
213 }
View Code

 

posted @ 2019-08-01 10:30  ATHOSD  阅读(95)  评论(0编辑  收藏  举报