1. 程式人生 > >bzoj 2212 Tree Rotations

bzoj 2212 Tree Rotations

題目大意:

一棵二叉樹,所有非葉子節點都有兩個孩子

在每個葉子節點上有一個權值 可以任意交換每個非葉子節點的左右孩子

要求進行一系列交換,使得最終所有葉子節點的權值按照順序寫出來,逆序對個數最少

思路:

建立權值線段樹

dfs時 對於每個節點 判斷交換更好還是不交換好 再加上左右兒子的答案向上繼續傳遞答案

判斷的時候merge

 1  
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cstdlib>
 6
#include<cstring> 7 #include<algorithm> 8 #include<vector> 9 #include<queue> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 400100 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') f=-1
;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 int n,o,rt[MAXN],tot,ch[MAXN][2],val[MAXN],ls[MAXN<<5],rs[MAXN<<5]; 22 ll ansl,ansr,sum[MAXN<<5]; 23 void init(int &x) 24 { 25 if(!x) x=++tot; 26 val[x]=read(); 27 if(!val[x]) {init(ch[x][0
]);init(ch[x][1]);} 28 } 29 void mdf(int &k,int l,int r,int x) 30 { 31 k=++tot; 32 if(l==r) {sum[k]=1;return ;} 33 int mid=(l+r)>>1; 34 if(x<=mid) mdf(ls[k],l,mid,x); 35 else mdf(rs[k],mid+1,r,x); 36 sum[k]=sum[ls[k]]+sum[rs[k]]; 37 } 38 int merge(int a,int b) 39 { 40 if(!a||!b) return a+b; 41 ansl+=sum[rs[a]]*sum[ls[b]]; 42 ansr+=sum[ls[a]]*sum[rs[b]]; 43 ls[a]=merge(ls[a],ls[b]); 44 rs[a]=merge(rs[a],rs[b]); 45 sum[a]=sum[ls[a]]+sum[rs[a]]; 46 return a; 47 } 48 ll dfs(int x) 49 { 50 ll res=0; 51 if(!val[x]) 52 { 53 res=dfs(ch[x][0])+dfs(ch[x][1]); 54 ansl=ansr=0; 55 rt[x]=merge(rt[ch[x][0]],rt[ch[x][1]]); 56 res+=min(ansl,ansr); 57 } 58 else mdf(rt[x],1,n,val[x]); 59 return res; 60 } 61 int main() 62 { 63 n=read(); 64 init(o);tot=0; 65 printf("%lld",dfs(1)); 66 }
View Code