[bzoj2212]Tree Rotations

初始对于每一个叶子节点建一棵权值线段树,然后再线段树合并时计算一下两者分别在前面和后面的代价,$ans+=min(\sum sz[rz[x]]\cdot sz[ls[y]],\sum sz[ls[x]]\cdot sz[rs[y]])$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define N 200001
 5 #define mid (l+r>>1)
 6 int V,n,ls[N*20],rs[N*20];
 7 ll ans,ans1,ans2,sz[N*20];
 8 void update(int k,int l,int r,int x){
 9     sz[k]=1;
10     if (l==r)return;
11     if (x<=mid)update(ls[k]=++V,l,mid,x);
12     else update(rs[k]=++V,mid+1,r,x);
13 }
14 int merge(int x,int y){
15     if (x*y==0)return x+y;
16     if (ls[x]+rs[x]==0)sz[x]+=sz[y];
17     else{
18         ans1+=sz[ls[x]]*sz[rs[y]];
19         ans2+=sz[rs[x]]*sz[ls[y]];
20         sz[x]=sz[ls[x]=merge(ls[x],ls[y])]+sz[rs[x]=merge(rs[x],rs[y])];
21     }
22     return x;
23 }
24 int dfs(){
25     int x,r,r1=0,r2=0;
26     scanf("%d",&x);
27     if (x){
28         update(r=++V,1,n,x);
29         return r;
30     }
31     r1=dfs();
32     r2=dfs();
33     ans1=ans2=0;
34     r=merge(r1,r2);
35     ans+=min(ans1,ans2);
36     return r;
37 }
38 int main(){
39     scanf("%d",&n);
40     dfs();
41     printf("%lld",ans);
42 }
View Code

 

posted @ 2019-07-28 10:40  PYWBKTDA  阅读(135)  评论(0编辑  收藏  举报