zoukankan      html  css  js  c++  java
  • 【NOIP2013】 火柴排队 贪心+splay

    这题为啥我写得这么复杂。

    首先我们不难发现,我们将序列$a$和序列$b$排序,考虑两序列内无相同元素,那么最小值显然为$sum_{i=1}^{n} (a_i-b_i)^2$。

    下面考虑做法

    首先,我们将序列$a$和序列$b$离散化(以下提及序列$a$和$b$均为离散化后的数字)

    然后,我们从前往后枚举序列$a$中的每一个数字,对于序列$a$中第$i$个数字$a_i$,我们在序列$b$中找出数字$a_i$的出现位置,并把它移动到序列$b$中第$i$个位置,与$a_i$对齐。

    对于序列$b$,我们用一个$splay$来维护,其中会出现插入和删除操作。

    时间复杂度:$O(n log n)$。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<set>
     7 #include<map>
     8 #include<queue>
     9 #include<vector>
    10 #define M 100005
    11 #define L long long
    12 #define MOD 99999997
    13 #define lc(x) ch[x][0]
    14 #define rc(x) ch[x][1]
    15 using namespace std;
    16 
    17 L ans=0,n,a[M]={0},b[M]={0},c[M]={0},wei[M]={0};
    18 L ch[M][2]={0},siz[M]={0},fa[M]={0},root=0;
    19 
    20 void pushup(L x){siz[x]=siz[lc(x)]+siz[rc(x)]+1;}
    21 void rotate(L x,L &k){
    22     L y=fa[x],z=fa[y];
    23     if(y==k) k=x;
    24     else{
    25         if(lc(z)==y) lc(z)=x;
    26         else rc(z)=x;
    27     }
    28     L l=(lc(y)!=x),r=l^1;
    29     fa[y]=x; fa[x]=z; fa[ch[x][r]]=y;
    30     ch[y][l]=ch[x][r]; ch[x][r]=y;
    31     pushup(y); 
    32     pushup(x);
    33 }
    34 void splay(L x,L &k){
    35     while(x!=k){
    36         L y=fa[x],z=fa[y];
    37         if(y!=k){
    38             if((lc(z)==y)^(lc(y)==x)) rotate(x,k);
    39             else rotate(y,k);
    40         }
    41         rotate(x,k);
    42     }
    43 }
    44 
    45 void ins(L &x,L k,L id){
    46     if(!x) return void(x=id);
    47     if(k<=siz[lc(x)]) ins(lc(x),k,id),fa[lc(x)]=x;
    48     else ins(rc(x),k-siz[lc(x)]-1,id),fa[rc(x)]=x;
    49     pushup(x);
    50 }
    51 void del(L id){
    52     splay(id,root);
    53     L x=lc(id),y=rc(id);
    54     siz[id]=1; fa[x]=fa[y]=0;
    55     lc(id)=rc(id)=0;
    56     if(!x) return void(root=y);
    57     if(!y) return void(root=x);
    58     root=x;
    59     while(rc(x)) x=rc(x);
    60     rc(x)=y; fa[y]=x; 
    61     splay(x,root);
    62 }
    63 
    64 signed main(){
    65     scanf("%d",&n);
    66     for(L i=1;i<=n;i++) scanf("%lld",a+i),c[i]=a[i];
    67     sort(c+1,c+n+1);
    68     for(L i=1;i<=n;i++) a[i]=lower_bound(c+1,c+n+1,a[i])-c;
    69     for(L i=1;i<=n;i++) scanf("%lld",b+i),c[i]=b[i];
    70     sort(c+1,c+n+1);
    71     for(L i=1;i<=n;i++) b[i]=lower_bound(c+1,c+n+1,b[i])-c;
    72     for(L i=1;i<=n;i++) wei[b[i]]=i;
    73     
    74     for(L i=1;i<=n;i++){
    75         siz[i]=1;
    76         ins(root,i-1,i);
    77         splay(i,root);
    78     }
    79     for(L i=1;i<=n;i++){
    80         int x=wei[a[i]];
    81         splay(x,root);
    82         L nowid=siz[lc(x)]+1;
    83         del(x);
    84         ins(root,i-1,x);
    85         splay(x,root);
    86         ans+=abs(i-nowid);
    87     }
    88     cout<<ans%MOD<<endl;
    89 }
  • 相关阅读:
    独立与条件独立
    独立事件、笛卡尔积与矩阵向量乘法
    独立事件、笛卡尔积与矩阵向量乘法
    OpenCV图像增强算法实现(直方图均衡化、拉普拉斯、Log、Gamma)
    等高线的认识
    等高线的认识
    概率相关的证明
    概率相关的证明
    OpenGl中使用着色器的基本步骤及GLSL渲染简单示例
    中英文对照 —— 歌词
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/9745978.html
Copyright © 2011-2022 走看看