• bzoj3702二叉树 线段树合并


    3702: 二叉树

    Time Limit: 15 Sec  Memory Limit: 256 MB
    Submit: 600  Solved: 272
    [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。

     

    两棵子树交换不影响子树内的值,所以每次只考虑相邻两棵子树怎样放,再考虑上一层怎么放

    线段树合并: 开权值线段记录原树中每个节点的子树对应拥有的值,向上合并的时候统计答案

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #define ll long long
    #define N 200050
    using namespace std;
    int n,tot,cnt,v[N*3],rt[N*3],l[N*3],r[N*3],ls[N*20],rs[N*20],sum[N*20];
    ll ans,a,b;
    void tree(int &x){
        x=++tot;
        scanf("%d",&v[tot]);
        if(v[tot])return;
        tree(l[x]);
        tree(r[x]);
    }
    void update(int &u,int l,int r,int p){
        if(!u)u=++cnt;sum[u]++;
        if(l==r)return;
        int mid=l+r>>1;
        if(p<=mid)update(ls[u],l,mid,p);
        else update(rs[u],mid+1,r,p);
    }
    int merge(int x,int y){
        if(!x)return y;
        if(!y)return x;
        a+=1ll*sum[ls[x]]*sum[rs[y]];
        b+=1ll*sum[rs[x]]*sum[ls[y]];
        ls[x]=merge(ls[x],ls[y]);
        rs[x]=merge(rs[x],rs[y]);
        sum[x]=sum[ls[x]]+sum[rs[x]];
        return x;
    }
    
    void solve(int x){
        if(!x)return;
        solve(l[x]);solve(r[x]);
        if(v[x])return;
        a=0;b=0;
        rt[x]=merge(rt[l[x]],rt[r[x]]);
        ans+=min(a,b);
    }
    
    int main(){
        scanf("%d",&n);
        int root;tree(root);
        for(int i=1;i<=tot;i++)
        if(v[i])update(rt[i],1,n,v[i]);
        solve(1);cout<<ans;
        return 0;
    }
  • 相关阅读:
    解决mybatis查询返回结果值串查
    MSSQL Export Excel
    Linux检测硬盘读取速度
    Linux修改用户密码
    Linux系统关闭防火墙端口
    Linux系统查看系统信息
    查找一个String中存储的多个数据
    编辑器vi命令
    去除一段文字最后一个符号
    替换Jar包中的一个文件 Replace a file in a JAR
  • 原文地址:https://www.cnblogs.com/wsy01/p/8076054.html
Copyright © 2020-2023  润新知