• 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
    ",ans);
        return 0;
    }
    
    

      

  • 相关阅读:
    css最简单的在背景图片上显示模糊背景色的方法
    css添加网格背景
    获取bing必应图片
    JavaScript超过一定高度导航添加类名
    6行css就可以解决的瀑布流布局的方法
    css实现背景图横向滚动
    JavaScript根据一个元素的显示隐藏控制另一个元素的显示和隐藏
    JavaScript判断地址栏链接与导航栏链接是否一致并给导航添加class
    JavaScript实现选中文字自动复制
    Day 74 算法基础(二)
  • 原文地址:https://www.cnblogs.com/something-for-nothing/p/9509305.html
Copyright © 2020-2023  润新知