【bzoj3702】二叉树
2017-12-26 13:19
141 查看
Description
现在有一棵二叉树,所有非叶子节点都有两个孩子。在每个叶子节点上有一个权值(有n个叶子节点,满足这些权值为1..n的一个排列)。可以任意交换每个非叶子节点的左右孩子。
要求进行一系列交换,使得最终所有叶子节点的权值按照中序遍历写出来,逆序对个数最少。
Input
第一行n
下面每行,一个数x
如果x==0,表示这个节点非叶子节点,递归地向下读入其左孩子和右孩子的信息,
如果x!=0,表示这个节点是叶子节点,权值为x。
Output
一行,最少逆序对个数。
Sample Input
3
0
0
3
1
2
Sample Output
1
HINT
对于100%的数据:2<=n<=200000。
题解
线段树合并。
我们发现交换两个儿子,则每个儿子原有的逆序对数量不会改变。
于是我们自底向上贪心,每次使节点的逆序对数量尽量少。
对于每个点开权值线段树,代表有哪几个权值的点,合并左右儿子,利用合并的性质判断是否交换。
代码
现在有一棵二叉树,所有非叶子节点都有两个孩子。在每个叶子节点上有一个权值(有n个叶子节点,满足这些权值为1..n的一个排列)。可以任意交换每个非叶子节点的左右孩子。
要求进行一系列交换,使得最终所有叶子节点的权值按照中序遍历写出来,逆序对个数最少。
Input
第一行n
下面每行,一个数x
如果x==0,表示这个节点非叶子节点,递归地向下读入其左孩子和右孩子的信息,
如果x!=0,表示这个节点是叶子节点,权值为x。
Output
一行,最少逆序对个数。
Sample Input
3
0
0
3
1
2
Sample Output
1
HINT
对于100%的数据:2<=n<=200000。
题解
线段树合并。
我们发现交换两个儿子,则每个儿子原有的逆序对数量不会改变。
于是我们自底向上贪心,每次使节点的逆序对数量尽量少。
对于每个点开权值线段树,代表有哪几个权值的点,合并左右儿子,利用合并的性质判断是否交换。
代码
#include<bits/stdc++.h> #define ll long long #define inf 1000000000 using namespace std; const int N=200005; const int mod=1000000007; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } ll ans,a,b; int n,sz,tot,v[N<<1],rt[N<<1],l[N<<1],r[N<<1]; int t[N*20],ls[N*20],rs[N*20]; void tree(int x) { v[x]=read(); if (v[x]==0) { l[x]=++sz; tree(l[x]); r[x]=++sz; tree(r[x]); } } void build(int &k,int l,int r,int x) { if (!k) k=++tot;t[k]++; if (l==r) return; int mid=(l+r)>>1; if (x<=mid) build(ls[k],l,mid,x);else build(rs[k],mid+1,r,x); } int merge(int x,int y) { if (!x) return y; if (!y) return x; a+=(ll)t[ls[x]]*t[rs[y]]; b+=(ll)t[ls[y]]*t[rs[x]]; ls[x]=merge(ls[x],ls[y]); rs[x]=merge(rs[x],rs[y]); t[x]=t[ls[x]]+t[rs[x]]; return x; } void solve(int x) { if (!x) return; solve(l[x]);solve(r[x]); if (!v[x]) { a=b=0; rt[x]=merge(rt[l[x]],rt[r[x]]); ans+=min(a,b); } } int main() { n=read(); sz=1;tree(1); for (int i=1;i<=sz;i++) if (v[i]) build(rt[i],1,n,v[i]); solve(1); cout<<ans; return 0; }
相关文章推荐
- bzoj3702 二叉树
- 【bzoj3702】二叉树 权值线段树
- [POI2011]Rotacje na drzewie (2)/[BZOJ3702]二叉树
- bzoj3702 二叉树
- [bzoj3702] 二叉树
- bzoj 3702: 二叉树 线段树合并
- bzoj3702二叉树 线段树合并
- [bzoj3702]二叉树
- bzoj3702二叉树 线段树合并
- 【bzoj3702】【二叉树】【线段树】
- bzoj 3702: 二叉树
- bzoj 3702 二叉树
- bzoj 3702: 二叉树 (线段树)
- [bzoj3702]二叉树
- bzoj1864: [Zjoi2006]三色二叉树
- BZOJ -1864: [Zjoi2006]三色二叉树
- BZOJ3625: [Codeforces Round #250]小朋友和二叉树
- BZOJ 1864 [Zjoi2006] 三色二叉树
- BZOJ1864 [Zjoi2006]三色二叉树
- [bzoj1864][Zjoi2006]三色二叉树(树上dp)