• bzoj2244 [SDOI2011]拦截导弹


    传送门

    这题其实没那么难,只是我做法麻烦所以调起来相当费事儿……这人没救了

    第一问显然是裸的三维偏序,分治随便搞搞就行了。考虑第二问,答案其实就是包括它的子序列数除以总方案数,那么定义$g[i]$为以i结尾的子序列数量,$h[i]$为以i开头的子序列数量,包括它的子序列数就是$g[i]h[i]$了。

    而$g[i],h[i]$的转移方程分别是:

    egin{align}g[i]=sum_{j<i,a_j<a_i,f[j]=f[i]-1}g[j]end{align}

    egin{align}g[i]=1(f[i]=1)end{align}

    egin{align}h[i]=sum_{i<j,a_i<a_j,f[i]=f[j]-1}h[j]end{align}

    egin{align}h[i]=1(f[i]=max_{j=1}^n{f[j]})end{align}

    (注:这里的$<$都是指满足题中的偏序关系)

    不难看出这还是三维偏序的形式,再跑两遍分治即可。

    三遍分治都是手打的,没有用复制粘贴,写了好久……超过200行的分治,真是醉了……

      1 /**************************************************************
      2     Problem: 2244
      3     User: hzoier
      4     Language: C++
      5     Result: Accepted
      6     Time:4636 ms
      7     Memory:6368 kb
      8 ****************************************************************/
      9 #include<cstdio>
     10 #include<cstring>
     11 #include<algorithm>
     12 #include<vector>
     13 using namespace std;
     14 const int maxn=50010;
     15 struct A{
     16     int x,y,id;
     17     bool ins;
     18     bool operator<(const A &a)const{
     19         if(x!=a.x)return x<a.x;
     20         return ins&&!a.ins;
     21     }
     22 }a[maxn],aa[maxn],b[maxn];
     23 bool cmp(const A &a,const A &b){
     24     if(a.x!=b.x)return a.x>b.x;
     25     return a.ins&&!b.ins;
     26 }
     27 void CDQ1(int,int);
     28 void CDQ2(int,int);
     29 void CDQ3(int,int);
     30 void add1(int,int);
     31 void add2(int,long double);
     32 int query1(int);
     33 long double query2(int);
     34 void clear1(int);
     35 void clear2(int);
     36 vector<int>vec[maxn];
     37 long double c2[maxn]={0},g[maxn]={0},h[maxn]={0},tmp=0.0;
     38 int n,t[maxn],f[maxn],c1[maxn],ans;
     39 int main(){
     40     scanf("%d",&n);
     41     for(int i=1;i<=n;i++){
     42         scanf("%d%d",&a[i].x,&a[i].y);
     43         t[i]=a[i].y;
     44         a[i].id=i;
     45         f[i]=1;
     46     }
     47     sort(t+1,t+n+1);
     48     for(int i=1;i<=n;i++)a[i].y=lower_bound(t+1,t+n+1,a[i].y)-t;
     49     copy(a+1,a+n+1,aa+1);
     50     CDQ1(1,n);
     51     for(int i=1;i<=n;i++){
     52         ans=max(ans,f[i]);
     53         vec[f[i]].push_back(i);
     54     }
     55     printf("%d
    ",ans);
     56     for(int i=0;i<(int)vec[1].size();i++)g[vec[1][i]]=1.0;
     57     for(int k=2;k<=ans;k++){
     58         int i=0,j=0,cnt=0;
     59         while(i<(int)vec[k-1].size()&&j<(int)vec[k].size()){
     60             if(vec[k-1][i]<vec[k][j]){
     61                 b[++cnt]=aa[vec[k-1][i]];
     62                 b[cnt].ins=true;
     63                 i++;
     64             }
     65             else{
     66                 b[++cnt]=aa[vec[k][j]];
     67                 b[cnt].ins=false;
     68                 j++;
     69             }
     70         }
     71         while(i<(int)vec[k-1].size()){
     72             b[++cnt]=aa[vec[k-1][i]];
     73             b[cnt].ins=true;
     74             i++;
     75         }
     76         while(j<(int)vec[k].size()){
     77             b[++cnt]=aa[vec[k][j]];
     78             b[cnt].ins=false;
     79             j++;
     80         }
     81         CDQ2(1,cnt);
     82     }
     83     for(int i=0;i<(int)vec[ans].size();i++){
     84         tmp+=g[vec[ans][i]];
     85         h[vec[ans][i]]=1.0;
     86     }
     87     for(int k=ans-1;k;k--){
     88         int i=0,j=0,cnt=0;
     89         while(i<(int)vec[k+1].size()&&j<(int)vec[k].size()){
     90             if(vec[k+1][i]<vec[k][j]){
     91                 b[++cnt]=aa[vec[k+1][i]];
     92                 b[cnt].ins=true;
     93                 i++;
     94             }
     95             else{
     96                 b[++cnt]=aa[vec[k][j]];
     97                 b[cnt].ins=false;
     98                 j++;
     99             }
    100         }
    101         while(i<(int)vec[k+1].size()){
    102             b[++cnt]=aa[vec[k+1][i]];
    103             b[cnt].ins=true;
    104             i++;
    105         }
    106         while(j<(int)vec[k].size()){
    107             b[++cnt]=aa[vec[k][j]];
    108             b[cnt].ins=false;
    109             j++;
    110         }
    111         CDQ3(1,cnt);
    112     }
    113     for(int i=1;i<=n;i++)printf("%.10lf ",(double)(g[i]*h[i]/tmp));
    114     return 0;
    115 }
    116 void CDQ1(int l,int r){
    117     if(l>=r)return;
    118     int mid=(l+r)>>1;
    119     CDQ1(l,mid);
    120     copy(aa+l,aa+r+1,a+l);
    121     sort(a+l,a+mid+1,cmp);
    122     sort(a+mid+1,a+r+1,cmp);
    123     int i=l,j=mid+1;
    124     while(i<=mid&&j<=r){
    125         if(a[i].x>=a[j].x){
    126             add1(n-a[i].y+1,f[a[i].id]);
    127             i++;
    128         }
    129         else{
    130             f[a[j].id]=max(f[a[j].id],query1(n-a[j].y+1)+1);
    131             j++;
    132         }
    133     }
    134     while(j<=r){
    135         f[a[j].id]=max(f[a[j].id],query1(n-a[j].y+1)+1);
    136         j++;
    137     }
    138     for(i=l;i<=mid;i++)clear1(n-a[i].y+1);
    139     CDQ1(mid+1,r);
    140 }
    141 void CDQ2(int l,int r){
    142     if(l>=r)return;
    143     int mid=(l+r)>>1;
    144     CDQ2(l,mid);
    145     copy(b+l,b+r+1,a+l);
    146     sort(a+l,a+mid+1,cmp);
    147     sort(a+mid+1,a+r+1,cmp);
    148     int i=l,j=mid+1;
    149     while(i<=mid&&j<=r){
    150         if(a[i].x>a[j].x||(a[i].x==a[j].x&&a[i].ins)){
    151             if(a[i].ins)add2(n-a[i].y+1,g[a[i].id]);
    152             i++;
    153         }
    154         else{
    155             if(!a[j].ins)g[a[j].id]+=query2(n-a[j].y+1);
    156             j++;
    157         }
    158     }
    159     while(i<=mid){
    160         if(a[i].ins)add2(n-a[i].y+1,g[a[i].id]);
    161         i++;
    162     }
    163     while(j<=r){
    164         if(!a[j].ins)g[a[j].id]+=query2(n-a[j].y+1);
    165         j++;
    166     }
    167     for(i=l;i<=mid;i++)if(a[i].ins)clear2(n-a[i].y+1);
    168     CDQ2(mid+1,r);
    169 }
    170 void CDQ3(int l,int r){
    171     if(l>=r)return;
    172     int mid=(l+r)>>1;
    173     CDQ3(mid+1,r);
    174     copy(b+l,b+r+1,a+l);
    175     sort(a+l,a+mid+1);
    176     sort(a+mid+1,a+r+1);
    177     int i=mid+1,j=l;
    178     while(i<=r&&j<=mid){
    179         if(a[i].x<a[j].x||(a[i].x==a[j].x&&a[i].ins)){
    180             if(a[i].ins)add2(a[i].y,h[a[i].id]);
    181             i++;
    182         }
    183         else{
    184             if(!a[j].ins)h[a[j].id]+=query2(a[j].y);
    185             j++;
    186         }
    187     }
    188     while(i<=r){
    189         if(a[i].ins)add2(a[i].y,h[a[i].id]);
    190         i++;
    191     }
    192     while(j<=mid){
    193         if(!a[j].ins)h[a[j].id]+=query2(a[j].y);
    194         j++;
    195     }
    196     for(int i=mid+1;i<=r;i++)if(a[i].ins)clear2(a[i].y);
    197     CDQ3(l,mid);
    198 }
    199 void add1(int x,int d){
    200     while(x<=n){
    201         c1[x]=max(c1[x],d);
    202         x+=x&-x;
    203     }
    204 }
    205 void add2(int x,long double d){
    206     while(x<=n){
    207         c2[x]+=d;
    208         x+=x&-x;
    209     }
    210 }
    211 int query1(int x){
    212     int ans=0;
    213     while(x){
    214         ans=max(ans,c1[x]);
    215         x&=x-1;
    216     }
    217     return ans;
    218 }
    219 long double query2(int x){
    220     long double ans=0.0;
    221     while(x){
    222         ans+=c2[x];
    223         x&=x-1;
    224     }
    225     return ans;
    226 }
    227 void clear1(int x){
    228     while(x<=n){
    229         c1[x]=0;
    230         x+=x&-x;
    231     }
    232 }
    233 void clear2(int x){
    234     while(x<=n){
    235         c2[x]=0.0;
    236         x+=x&-x;
    237     }
    238 }
    View Code

    有一些做法可以一边分治一边求出$g$,然后再跑一遍分治就能求出$h$,可以减少代码量?听说lrd写的就是这个?表示还没理解清楚……

  • 相关阅读:
    Web安全测试
    性能测试---并发用户计算
    浅谈软件性能测试中关键指标的监控与分析
    fiddler抓包——IOS
    Linux下查看CPU型号,内存大小,硬盘空间,进程等的命令(详解)
    windows 升级pip
    java 使用Iterator 迭代器遍历AList、Set、Map
    springboot 封装redis工具类
    idea 取消@Autowired 不建议字段注入的警告
    查看服务器相关
  • 原文地址:https://www.cnblogs.com/hzoier/p/6416656.html
Copyright © 2020-2023  润新知