1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #define M 100009 5 using namespace std; 6 struct data 7 { 8 int x,y,z,f[2]; 9 double sum[2]; 10 }a[M],b[M]; 11 struct ss 12 { 13 int w; 14 double su; 15 }shu[M]; 16 int n,yy[M],zz[M],yl,zl,ans,tot,sta[M]; 17 double sum1; 18 bool cmp(data a1,data a2) 19 { 20 if(a1.y==a2.y) 21 return a1.x<a2.x; 22 return a1.y<a2.y; 23 } 24 bool cmp1(data a1,data a2) 25 { 26 return a1.x>a2.x; 27 } 28 void updata(int i,int p) 29 { 30 int a1=a[i].z; 31 for(;a1<=zl;a1+=a1&-a1) 32 if(shu[a1].w<a[i].f[p]) 33 { 34 if(shu[a1].w==0) 35 sta[++tot]=a1; 36 shu[a1].w=a[i].f[p]; 37 shu[a1].su=a[i].sum[p]; 38 } 39 else if(shu[a1].w==a[i].f[p]) 40 shu[a1].su+=a[i].sum[p]; 41 return; 42 } 43 void ask(int i,int p) 44 { 45 int a1=a[i].z; 46 for(;a1;a1-=a1&-a1) 47 if(a[i].f[p]<=shu[a1].w&&shu[a1].w) 48 { 49 a[i].f[p]=shu[a1].w+1; 50 a[i].sum[p]=shu[a1].su; 51 } 52 else if(a[i].f[p]==shu[a1].w+1) 53 a[i].sum[p]+=shu[a1].su; 54 return; 55 } 56 void solve(int l,int r,int p) 57 { 58 if(l==r) 59 { 60 if(a[l].f[p]==0) 61 a[l].f[p]=a[l].sum[p]=1; 62 return; 63 } 64 int mid=(l+r)>>1; 65 int l1=l,l2=mid+1; 66 for(int i=l;i<=r;i++) 67 if(a[i].x<=mid) 68 b[l1++]=a[i]; 69 else 70 b[l2++]=a[i]; 71 for(int i=l;i<=r;i++) 72 a[i]=b[i]; 73 solve(l,mid,p); 74 sort(a+l,a+mid+1,cmp); 75 int st=l; 76 for(int i=mid+1;i<=r;i++) 77 { 78 for(;a[st].y<=a[i].y&&st<=mid;st++) 79 updata(st,p); 80 ask(i,p); 81 } 82 for(int i=1;i<=tot;i++) 83 shu[sta[i]].w=shu[sta[i]].su=0; 84 tot=0; 85 solve(mid+1,r,p); 86 } 87 int main() 88 { 89 scanf("%d",&n); 90 for(int i=1;i<=n;i++) 91 { 92 a[i].x=i; 93 scanf("%d%d",&a[i].y,&a[i].z); 94 yy[i]=a[i].y; 95 zz[i]=a[i].z; 96 } 97 sort(yy+1,yy+n+1); 98 sort(zz+1,zz+n+1); 99 yl=unique(yy+1,yy+n+1)-yy-1; 100 zl=unique(zz+1,zz+n+1)-zz-1; 101 for(int i=1;i<=n;i++) 102 { 103 a[i].y=yl-(lower_bound(yy+1,yy+yl+1,a[i].y)-yy)+1; 104 a[i].z=zl-(lower_bound(zz+1,zz+zl+1,a[i].z)-zz)+1; 105 } 106 sort(a+1,a+n+1,cmp); 107 solve(1,n,0); 108 for(int i=1;i<=n;i++) 109 { 110 a[i].x=n-a[i].x+1; 111 a[i].y=yl-a[i].y+1; 112 a[i].z=zl-a[i].z+1; 113 } 114 sort(a+1,a+n+1,cmp); 115 solve(1,n,1); 116 sort(a+1,a+n+1,cmp1); 117 for(int i=1;i<=n;i++) 118 if(a[i].f[0]>ans) 119 { 120 ans=a[i].f[0]; 121 sum1=a[i].sum[0]; 122 } 123 else if(a[i].f[0]==ans) 124 sum1+=a[i].sum[0]; 125 printf("%d ",ans); 126 for(int i=1;i<=n;i++) 127 if(a[i].f[0]+a[i].f[1]-1==ans) 128 printf("%.5lf ",a[i].sum[1]*a[i].sum[0]/sum1); 129 else 130 printf("0.00000 "); 131 return 0; 132 }
首先第一问明显是一个三维偏序集,速度,高度,时间,用CDQ分治做,然后我们把它反过来,在做一边CDQ分治,这两遍求出来的方案数组相乘,就是过这个点的方案数。