BZOJ 3702 二叉树

3702: 二叉树

Time Limit: 15 Sec  Memory Limit: 256 MB
Submit: 665  Solved: 307
[Submit][Status][Discuss]

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。

 

Source

直接上线段树合并即可

https://www.cnblogs.com/Mychael/p/8665589.html

/**************************************************************
    Problem: 3702
    User: zhangenming
    Language: C++
    Result: Accepted
    Time:7324 ms
    Memory:86028 kb
****************************************************************/
 
#include <bits/stdc++.h>
#define ll long long
#define inf 1e9+10
#define ull unsigned long long
#define eps 1e-7
using namespace std;
inline int read(){
    int x=0;int f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int MAXN=1e6+10;
struct sig{
    int sum,ls,rs;
}T[MAXN<<2];
int rt[MAXN],n,l[MAXN],r[MAXN],vl[MAXN],tot,siz;
ll sum1,sum2,ans;
inline void build(int &x){
    int t=read();x=++tot;
    if(t==0) build(l[x]),build(r[x]);
    else vl[x]=t;
}
inline void ins(int l,int r,int &rt,int t){
    if(!rt) rt=++siz;
    T[rt].sum++;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(t<=mid) ins(l,mid,T[rt].ls,t);
    else ins(mid+1,r,T[rt].rs,t);
}
inline int merge(int x,int y){
    if(!x||!y) return x+y;
    sum1+=1LL*T[T[x].rs].sum*T[T[y].ls].sum;
    sum2+=1LL*T[T[x].ls].sum*T[T[y].rs].sum;
    T[x].sum+=T[y].sum;
    T[x].ls=merge(T[x].ls,T[y].ls);
    T[x].rs=merge(T[x].rs,T[y].rs);
    return x;
}
inline void dfs(int x){
    if(vl[x]){
        ins(1,n,rt[x],vl[x]);
    }
    else{
        dfs(l[x]);dfs(r[x]);
        sum1=sum2=0;
        rt[x]=merge(rt[l[x]],rt[r[x]]);
        ans+=min(sum1,sum2);
    }
}
int main(){
    n=read();
    int root;
    build(root);
    dfs(root);
    printf("%lld\n",ans);
    return 0;
}

  

posted @ 2018-08-21 08:44  zhangenming  阅读(201)  评论(0编辑  收藏  举报