zoukankan      html  css  js  c++  java
  • P2487 [SDOI2011]拦截导弹

    链接

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

    (Max=maxlimits_{i=1}^n{f_{i,1}},sum=sumlimits_{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})

    ( herefore 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
    ",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("
    ");
      return 0;
    }
    
  • 相关阅读:
    [转]Annotation手册
    [转]十款非主流操作系统介绍
    关于构造函数及游离块的顺序
    如何申请Google地图API Key
    “请求响应”模式和“事件驱动”模式
    【引用】Linux中硬链接和软链接的区别和联系
    [转]Java代码的静态编译和动态编译中的问题比较
    [转]Java中常用设计模式总结
    GIS名词解释
    [转]比较JSF、Spring MVC、Stripes、Struts2、Tapestry、Wicket
  • 原文地址:https://www.cnblogs.com/yiqiAtiya/p/14028499.html
Copyright © 2011-2022 走看看