显然可以对时间CDQ分治,然后按高度排序,对速度用BIT维护前缀最大值。
这样就可以算第一问。
对于第二问。
思维不要僵化。
BIT可以在维护前缀最大值的同时维护方案数的。
额。。。
AC Code:
#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
int n,h[maxn],v[maxn],sh[maxn],sv[maxn],c[maxn];
int f[maxn],rf[maxn];
double g[maxn],rg[maxn];
bool cmp(const int &u,const int &v){ return h[u] == h[v] ? u < v : h[u] > h[v]; }
int Max[maxn],del[maxn],tp;
double Cnt[maxn];
void upd(int now,int val,double ways){
for(;now<=sv[0];now+=now&-now){
if(Max[now] == 0) del[tp++] = now;
if(val>Max[now]) Max[now]=val,Cnt[now]=ways;
else if(Max[now] == val) Cnt[now] += ways;
}
}
pair<int,double> qsum(int now){
pair<int,double>ret=make_pair(0,0);
for(;now;now-=now&-now)
if(ret.first < Max[now]) ret.first=Max[now],ret.second=Cnt[now];
else if(ret.first == Max[now]) ret.second += Cnt[now];
return ret;
}
void Solve(int l,int r,int *f,double *g){
if(l>=r){ if(!f[l]) f[l]=1,g[l]=1;return; }
int mid = (l+r) >> 1;
Solve(l,mid,f,g);
sort(c+l,c+mid+1,cmp);
sort(c+mid+1,c+r+1,cmp);
int j=l;
//printf("@%d %d %d\n",l,mid,r);
//for(int i=l;i<=r;i++) printf("%d\n",c[i]);
for(int i=mid+1;i<=r;i++){
for(;j<=mid && h[c[j]] >= h[c[i]];j++) {
//printf("%d %d %d\n",c[j],v[c[j]],f[c[j]]);
//printf("%d %d %.3lf\n",c[j],f[c[j]],g[c[j]]);
upd(v[c[j]],f[c[j]],g[c[j]]);
}
//printf("%d %d\n",c[i],v[c[i]]);
pair<int,double>ret=qsum(v[c[i]]);
//printf("%d $%.3lf\n",ret.first,ret.second);
//printf("%d %.3lf\n",f[2],g[2]);
if(!ret.second) continue;
if(ret.first+1>f[c[i]]) f[c[i]]=ret.first+1,g[c[i]]=ret.second;
else if(ret.first+1==f[c[i]]) g[c[i]]+=ret.second;
//printf("%d %.3lf\n",f[2],g[2]);
}
sort(c+mid+1,c+r+1);
for(;tp;) Max[del[--tp]]=0,Cnt[del[tp]]=0;
Solve(mid+1,r,f,g);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&h[i],&v[i]),sh[++sh[0]]=h[i],sv[++sv[0]]=v[i],c[i]=i;
sort(sh+1,sh+1+sh[0]),sort(sv+1,sv+1+sv[0]);
sh[0]=unique(sh+1,sh+1+sh[0])-sh-1;
sv[0]=unique(sv+1,sv+1+sv[0])-sv-1;
for(int i=1;i<=n;i++)
h[i] = lower_bound(sh+1,sh+1+sh[0],h[i])-sh,
v[i] = lower_bound(sv+1,sv+1+sv[0],v[i])-sv,
v[i] = sv[0] + 1 - v[i];
Solve(1,n,f,g);
for(int i=1;i<=n;i++)
v[i] = sv[0] + 1 - v[i],
h[i] = sh[0] + 1 - h[i];
for(int i=1;i<n-i+1;i++)
swap(v[i],v[n-i+1]),
swap(h[i],h[n-i+1]);
//for(int i=1;i<=n;i++)
// printf("%d %d\n",h[i],v[i]);
sort(c+1,c+1+n);
Solve(1,n,rf,rg);
for(int i=1;i<n-i+1;i++)
swap(rf[i],rf[n-i+1]),
swap(rg[i],rg[n-i+1]);
//for(int i=1;i<=n;i++) printf("%.3lf\n",g[i]);
int Max = *max_element(f+1,f+1+n);
printf("%d\n",Max);
double sum = 0;
for(int i=1;i<=n;i++)
if(f[i] == Max)
sum += g[i];
for(int i=1;i<=n;i++){
//printf("%.3lf %.3lf %.3lf\n",g[i],rg[i],sum);
printf("%.5lf%c",(f[i] + rf[i] == Max + 1) * g[i] * rg[i] / sum,i==n?'\n':' ');
}
}