bzoj 2244: [SDOI2011]拦截导弹

  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分治,这两遍求出来的方案数组相乘,就是过这个点的方案数。

原文地址:https://www.cnblogs.com/xydddd/p/5300035.html