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

猜你喜欢

转载自www.cnblogs.com/yyc-jack-0920/p/9806715.html