zoukankan      html  css  js  c++  java
  • BZOJ

    BZOJ - 2244 拦截导弹 (dp,CDQ分治+树状数组优化)

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #define MAXN 50010
     6 #define LL long long
     7 using namespace std;
     8 struct ddd
     9 {    
    10     int t,h,v,ans;    
    11     #define t(x) a[x].t
    12     #define h(x) a[x].h    
    13     #define v(x) a[x].v
    14     #define ans(x) a[x].ans
    15 }a[MAXN];
    16 int n,th[MAXN],tv[MAXN];
    17 bool cmp1(ddd a,ddd b){return a.t==b.t?(a.h==b.h?(a.v<b.v):a.h<b.h):a.t<b.t;}
    18 bool cmp2(ddd a,ddd b){return a.h==b.h?(a.t==b.t?(a.v>b.v):a.t<b.t):a.h>b.h;}
    19 int ans=1;
    20 int C[MAXN];
    21 #define lowbit(x) ((x)&(-(x)))
    22 //void add(int x,int y){while(x<=n){C[x]+=y;x+=lowbit(x);}}
    23 //int ask(int x){int ans=0;while(x){ans+=C[x];x-=lowbit(x);}return ans;}
    24 void add(int x,int y)
    25 {//cout<<"add "<<x<<" "<<y<<endl;
    26 while(x){C[x]=max(C[x],y);x-=lowbit(x);}}
    27 void admin(int x,int y)
    28 {while(x){C[x]=min(C[x],y);x-=lowbit(x);}}
    29 int ask(int x){int ans=0;while(x<=n){ans=max(ans,C[x]);x+=lowbit(x);}return ans;}
    30 void CDQ(int l,int r)
    31 {    
    32     if(l==r){return;}
    33     int mid=(l+r)>>1;
    34 //    sort(a+l,a+mid+1,cmp1);
    35     CDQ(l,mid);
    36     sort(a+l,a+mid+1,cmp2);
    37     sort(a+mid+1,a+r+1,cmp2);
    38     int j=l;
    39 //    cout<<"# "<<l<<" "<<r<<endl;
    40 //    for(int i=l;i<=r;i++)cout<<i<<": "<<t(i)<<" "<<h(i)<<" "<<v(i)<<endl;
    41     for(int i=mid+1;i<=r;i++)
    42     {
    43         while(j<=mid&&h(j)>=h(i)){//cout<<"!!!!!!!!j "<<j<<" "<<ans(j)<<endl;
    44         add(v(j),ans(j)),j++;}
    45         ans(i)=max(ans(i),ask(v(i))+1);//cout<<"!!!!!!!!!!ans "<<i<<" "<<ans(i)<<endl;
    46     }    
    47     for(int i=l;i<j;i++)admin(v(i),0);
    48     sort(a+mid+1,a+r+1,cmp1);
    49     CDQ(mid+1,r);    
    50 }
    51 signed main()
    52 {
    53 //    freopen("in.txt","r",stdin);
    54 
    55     cin>>n;
    56     for(int i=1;i<=n;i++)    
    57         cin>>h(i)>>v(i),t(i)=i,th[i]=h(i),tv[i]=v(i);
    58     sort(th+1,th+n+1);
    59     sort(tv+1,tv+n+1);
    60     int len1=unique(th+1,th+n+1)-th-1;
    61     int len2=unique(tv+1,tv+n+1)-tv-1;
    62     for(int i=1;i<=n;i++)
    63         h(i)=lower_bound(th+1,th+len1+1,h(i))-th,
    64         v(i)=lower_bound(tv+1,tv+len2+1,v(i))-tv;
    65     sort(a+1,a+n+1,cmp1);
    66     for(int i=1;i<=n;i++)ans(i)=1;
    67     CDQ(1,n);
    68     sort(a+1,a+n+1,cmp1);
    69 //    for(int i=1;i<=n;i++)cout<<"ans "<<i<<" "<<ans(i)<<endl;
    70     for(int i=1;i<=n;i++)ans=max(ans,ans(i));
    71     printf("%d
    ",ans);
    72     for(int i=1;i<=n;i++) cout<<(double)1/3<<" ";puts("");
    73 }
    第一问

    先说第一问吧,本来觉得挺简单的,做起来才发现一直调不出来……第一问其实是一个比较容易看出来的三位偏序问题,只不过并不是简单的求和,而是用一个点前面h和v都大于他的点答案的最大值+1去更新这个点,所以树状数组要维护后缀,记得要把每个点的初始答案附成1。

    第二问就比较麻烦了,一个点出现的概率等于$frac{包含这个点的方案数}{总方案数}$,维护4个数组,f[i]表示以i为结尾的最大长度,g[i]表示以i为结尾最大长度的方案数,h[i]表示以i开头的最大长度,s[i]表示以i开头最大长度的方案数。两个要跑两边CDQ,这里之说第一遍,用树状数组维护后缀最大值及其方案数(用结构体或pair实现),CDQ时先递归处理左区间,然后考虑当前区间,最后递归处理右区间。至于答案的更新:

    		if(tem.maxn==f(i))g(i)+=tem.num;
    		else if(tem.maxn>f(i))f(i)=tem.maxn,g(i)=tem.num;
    

     还有几点要注意:如果一个点不能包含在最长子序列中,那么选中他的概率为0。记得开double,这道题会爆longlong。

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<cmath>
      6 #define MAXN 50010
      7 #define LL long long
      8 #define int LL
      9 using namespace std;
     10 struct ddd
     11 {    
     12     int t,h,v,ans;
     13     double f,g,he,s;    
     14     #define t(x) a[x].t
     15     #define h(x) a[x].h    
     16     #define v(x) a[x].v
     17     #define ans(x) a[x].ans
     18     #define f(x) a[x].f
     19     #define g(x) a[x].g
     20     #define he(x) a[x].he
     21     #define s(x) a[x].s
     22 }a[MAXN];
     23 int n,th[MAXN],tv[MAXN];
     24 bool cmp1(ddd a,ddd b){return a.t==b.t?(a.h==b.h?(a.v<b.v):a.h<b.h):a.t<b.t;}
     25 bool cmp2(ddd a,ddd b){return a.h==b.h?(a.t==b.t?(a.v>b.v):a.t<b.t):a.h>b.h;}
     26 bool cmp3(ddd a,ddd b){return a.t==b.t?(a.h==b.h?(a.v<b.v):a.h<b.h):a.t>b.t;}
     27 bool cmp4(ddd a,ddd b){return a.h==b.h?(a.t==b.t?(a.v<b.v):a.t<b.t):a.h<b.h;}
     28 double ans=1;
     29 #define lowbit(x) ((x)&(-(x)))
     30 struct cc{double maxn;double num;}C[MAXN];
     31 void add(int x,double y,double nu)
     32 {
     33     while(x)
     34     {
     35         if(C[x].maxn==y)C[x].num+=nu;
     36         else if(C[x].maxn<y)C[x].maxn=y,C[x].num=nu;
     37         x-=lowbit(x);
     38     }
     39 }
     40 void admin(int x)
     41 {while(x){C[x].maxn=C[x].num=0;x-=lowbit(x);}}
     42 cc ask(int x)
     43 {
     44     cc ans={0,0};
     45     while(x<=n)
     46     {
     47         if(C[x].maxn==ans.maxn)ans.num+=C[x].num;
     48         else if(C[x].maxn>ans.maxn)ans.maxn=C[x].maxn,ans.num=C[x].num;
     49         x+=lowbit(x);
     50     }
     51     return ans;
     52 }
     53 cc C2[MAXN];
     54 void add2(int x,double y,double nu)
     55 {
     56     while(x<=n)
     57     {
     58         if(C2[x].maxn==y)C2[x].num+=nu;
     59         else if(C2[x].maxn<y)C2[x].maxn=y,C2[x].num=nu;
     60         x+=lowbit(x);
     61     }
     62 }
     63 void admin2(int x)
     64 {while(x<=n){C2[x].maxn=C2[x].num=0;x+=lowbit(x);}}
     65 cc ask2(int x)
     66 {
     67     cc ans={0,0};
     68     while(x)
     69     {
     70         if(C2[x].maxn==ans.maxn)ans.num+=C2[x].num;
     71         else if(C2[x].maxn>ans.maxn)ans.maxn=C2[x].maxn,ans.num=C2[x].num;
     72         x-=lowbit(x);
     73     }
     74     return ans;
     75 }
     76 void CDQ(int l,int r)
     77 {    
     78     if(l==r){return;}
     79     int mid=(l+r)>>1;
     80     CDQ(l,mid);
     81     sort(a+l,a+mid+1,cmp2);
     82     sort(a+mid+1,a+r+1,cmp2);
     83     int j=l;
     84     for(int i=mid+1;i<=r;i++)
     85     {
     86         while(j<=mid&&h(j)>=h(i))
     87         {
     88             add(v(j),f(j),g(j));j++;
     89         }
     90         cc tem=ask(v(i));tem.maxn++;
     91         if(tem.maxn==f(i))g(i)+=tem.num;
     92         else if(tem.maxn>f(i))f(i)=tem.maxn,g(i)=tem.num;
     93     }    
     94     for(int i=l;i<j;i++)admin(v(i));
     95     sort(a+mid+1,a+r+1,cmp1);
     96     CDQ(mid+1,r);    
     97 }
     98 void CDQ2(int l,int r)
     99 {    
    100     if(l==r){return;}
    101     int mid=(l+r)>>1;
    102     CDQ2(l,mid);
    103     sort(a+l,a+mid+1,cmp4);
    104     sort(a+mid+1,a+r+1,cmp4);
    105     int j=l;
    106     for(int i=mid+1;i<=r;i++)
    107     {
    108         while(j<=mid&&h(j)<=h(i))
    109         {
    110             add2(v(j),he(j),s(j));j++;
    111         }
    112         cc tem=ask2(v(i));tem.maxn++;
    113         if(tem.maxn==he(i))s(i)+=tem.num;
    114         else if(tem.maxn>he(i))he(i)=tem.maxn,s(i)=tem.num;
    115     }    
    116     for(int i=l;i<j;i++)admin2(v(i));
    117     sort(a+mid+1,a+r+1,cmp3);
    118     CDQ2(mid+1,r);    
    119 }
    120 signed main()
    121 {
    122 //    freopen("1.in","r",stdin);
    123 //    freopen("out.out","w",stdout);
    124 
    125     cin>>n;
    126     for(int i=1;i<=n;i++)    
    127         cin>>h(i)>>v(i),t(i)=i,th[i]=h(i),tv[i]=v(i);
    128     sort(th+1,th+n+1);
    129     sort(tv+1,tv+n+1);
    130     int len1=unique(th+1,th+n+1)-th-1;
    131     int len2=unique(tv+1,tv+n+1)-tv-1;
    132     for(int i=1;i<=n;i++)
    133         h(i)=lower_bound(th+1,th+len1+1,h(i))-th,
    134         v(i)=lower_bound(tv+1,tv+len2+1,v(i))-tv;
    135     for(int i=1;i<=n;i++)f(i)=g(i)=he(i)=s(i)=1;
    136     sort(a+1,a+n+1,cmp1);
    137     CDQ(1,n);
    138      for(int i=1;i<=n;i++)ans=max(ans,f(i));
    139     printf("%0.0lf
    ",ans);
    140     sort(a+1,a+n+1,cmp3);
    141     CDQ2(1,n);
    142     double summ=0;
    143     sort(a+1,a+n+1,cmp1);
    144     for(int i=1;i<=n;i++)
    145         if(fabs(f(i)-ans)<=1e-8) summ+=g(i);
    146     for(int i=1;i<=n;i++)
    147     {
    148         if(f(i)+he(i)-1==ans){double ttt=(double)(1.0*g(i)*s(i))/summ;printf("%0.5lf ",ttt);}
    149         else printf("0.00000 ");
    150     }puts("");
    151 }
    View Code

     

  • 相关阅读:
    SpringBoot-容器启动的时候执行一些内容
    Java JVM 启动参数
    leecode刷题(9)-- 有效的数独
    leecode刷题(8)-- 两数之和
    leecode刷题(7)-- 加一
    leecode刷题(6)-- 两个数组的交集II
    leecode刷题(5)-- 只出现一次的数字
    leecode刷题(4)-- 存在重复数组
    leecode刷题(3)-- 旋转数组
    leecode刷题(2)-- 买卖股票的最佳时机
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11291339.html
Copyright © 2011-2022 走看看