P2487 [SDOI2011]拦截导弹

链接

发现是三维偏序,用 \(CDQ\) 分治处理出每个数顺序和倒序的满足条件的最长长度与相应的方案数,分别设为 \(f1,f2,g1,g2\)

\(Max=\max\limits_{i=1}^n{f_{i,1}},sum=\sum\limits_{i=1}^n{[f_{i,1}=Max]\cdot g_{i,1}}\)

对于每个数,当 \(f_{i,1}+f_{i,2}-1=Max\) 时会在最长序列中,个数为 \(g_{i,1}\cdot g_{i,2}\)

\(\therefore ans_i=[f_{i,1}+f_{i,2}-1=Max]\frac{g_{i,1} \cdot g_{i,2}}{sum}\)

#include<bits/stdc++.h>
#define IL inline
#define LL long long
#define LF double
using namespace std;
const int N=5e4+3;
struct hh{
  int h,v,id;
}a[N],b[N];
struct kk{
  int f;LF g;
}dp1[N],dp2[N];
int n,bh[N],bv[N],Max;
LF sum;
IL int cmp1(hh a,hh b){return a.id<b.id;}
IL int cmp2(hh a,hh b){return a.h>b.h;}
IL int in(){
  char c;int f=1;
  while((c=getchar())<'0'||c>'9')
    if(c=='-') f=-1;
  int x=c-'0';
  while((c=getchar())>='0'&&c<='9')
    x=x*10+c-'0';
  return x*f;
}
struct BIT{
  int n;kk c[N];
  IL int lb(int x){return x&-x;}
  IL void add(int y,kk x){
	  for(;y<=n;y+=lb(y))
	    if(c[y].f<x.f) c[y]=x;
	    else if(c[y].f==x.f) c[y].g+=x.g;
	}
	IL kk ask(int y){
	  kk x=(kk){0,0};
	  for(;y;y-=lb(y))
	    if(x.f<c[y].f) x=c[y];
	    else if(x.f==c[y].f) x.g+=c[y].g;
	  return x;
	}
	IL void dele(int y){
	  kk x=(kk){0,0};
	  for(;y<=n;y+=lb(y)) c[y]=x;
	}
}T;
void solve1(int l,int r){
  if(l==r) return;
  int mid=l+r>>1;
  sort(b+l,b+r+1,cmp1);
  solve1(l,mid);
  sort(b+l,b+mid+1,cmp2),sort(b+mid+1,b+r+1,cmp2);
  int i,j;
  for(i=l-1,j=mid+1;j<=r;++j){
	  while(i<mid&&b[i+1].h>=b[j].h) ++i,T.add(T.n-b[i].v+1,dp1[b[i].id]);
	  kk res=T.ask(T.n-b[j].v+1);++res.f;
	  if(dp1[b[j].id].f<res.f) dp1[b[j].id]=res;
	  else if(dp1[b[j].id].f==res.f) dp1[b[j].id].g+=res.g;
	}
	for(int k=l;k<=i;++k) T.dele(T.n-b[k].v+1);
	solve1(mid+1,r);
}
void solve2(int l,int r){
  if(l==r) return;
  int mid=l+r>>1;
  sort(b+l,b+r+1,cmp1);
  solve2(mid+1,r);
  sort(b+l,b+mid+1,cmp2),sort(b+mid+1,b+r+1,cmp2);
  int i,j;
  for(i=r+1,j=mid;j>=l;--j){
	  while(i>mid+1&&b[i-1].h<=b[j].h) --i,T.add(b[i].v,dp2[b[i].id]);
	  kk res=T.ask(b[j].v);++res.f;
	  if(dp2[b[j].id].f<res.f) dp2[b[j].id]=res;
	  else if(dp2[b[j].id].f==res.f) dp2[b[j].id].g+=res.g;
	}
	for(int k=i;k<=r;++k) T.dele(b[k].v);
	solve2(l,mid);
}
int main()
{
	n=in();
	for(int i=1;i<=n;++i)
	  a[i]=(hh){bh[i]=in(),bv[i]=in(),i},dp1[i]=dp2[i]=(kk){1,1};
	sort(bv+1,bv+n+1),bv[0]=unique(bv+1,bv+n+1)-bv-1;
	for(int i=1;i<=n;++i) a[i].v=lower_bound(bv+1,bv+bv[0]+1,a[i].v)-bv;
	for(int i=1;i<=n;++i) b[i]=a[i];
	T.n=bv[0],solve1(1,n);
	for(int i=1;i<=n;++i) b[i]=a[i];
	solve2(1,n);
	for(int i=1;i<=n;++i) Max=max(Max,dp1[i].f);
	for(int i=1;i<=n;++i) if(Max==dp1[i].f) sum+=dp1[i].g;
	printf("%d\n",Max);
	for(int i=1;i<=n;++i)
	  if(dp1[i].f+dp2[i].f-1==Max)
	    printf("%lf ",dp1[i].g*dp2[i].g/sum);
	  else printf("0 ");
	printf("\n");
  return 0;
}
posted @ 2020-11-24 09:09  (o-ωq)).oO  阅读(94)  评论(0编辑  收藏  举报