【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 }

猜你喜欢

转载自www.cnblogs.com/xiefengze1/p/9745978.html