• [bzoj2212][Poi2011]Tree Rotations


    3702双倍经验。原题链接2212

    现在有一棵二叉树,所有非叶子节点都有两个孩子。在每个叶子节点上有一个权值(有$n$个叶子节点,满足这些权值为$1..n$的一个排列)。可以任意交换每个非叶子节点的左右孩子。
    要求进行一系列交换,使得最终所有叶子节点的权值按照中序遍历写出来,逆序对个数最少。

    一个节点的子树内的交换与其无关,只与它的左右子树内有多少逆序对有关。所以可以贪心,满足交换一个节点的左右儿子后逆序对最少即可。用线段树合并既可维护子树内的权值,还可以在merge操作时直接求出逆序对数。舍我其谁啊。

    两棵线段树合并时,递归的每一层都计算:

    $x$左子树(小于$mid$个数)与$y$右子树(大于$mid$个数)之积,为交换后的逆序对;

    $x$左子树(小于$mid$个数)与$y$右子树(大于$mid$个数)之积,为不交换的逆序对;

    都累加之后取$min$的那个。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=400010;
    inline int read(){
        int r=0,c=getchar();
        while(!isdigit(c))c=getchar();
        while(isdigit(c))
        r=r*10+c-'0',c=getchar();
        return r;
    }
    struct Node{
        int L,R,sum;
    }T[N*20];
    int rt[N],sz,n,cnt;
    int ll[N],rr[N],val[N];
    void getTree(int &x){
        x=++cnt;val[x]=read();
        if(val[x])return;
        getTree(ll[x]);
        getTree(rr[x]);
    }
    #define ls T[o].L
    #define rs T[o].R
    #define mid (l+r>>1)
    void pullup(int o){
        T[o].sum=T[ls].sum+T[rs].sum;
    }
    void ins(int &o,int l,int r,int v){
        o=++sz;
        if(l==r){
            T[o].sum=1;return;
        }
        if(v<=mid)ins(ls,l,mid,v);
        else ins(rs,mid+1,r,v);
        pullup(o);
    }
    LL ans,ans1,ans2;
    int merge(int x,int y){
        if(!x)return y;
        if(!y)return x;
        ans1+=1ll*T[T[x].L].sum*T[T[y].R].sum;
        ans2+=1ll*T[T[x].R].sum*T[T[y].L].sum;
        T[x].L=merge(T[x].L,T[y].L);
        T[x].R=merge(T[x].R,T[y].R);
        pullup(x);
        return x;
    }
    void dfs(int u){
        if(val[u])return;
        dfs(ll[u]);dfs(rr[u]);
        ans1=ans2=0;
        rt[u]=merge(rt[ll[u]],rt[rr[u]]);
        ans+=ans1<ans2?ans1:ans2;
    }
    void init(){
        n=read();
        int r;getTree(r);
        for(int i=1;i<=cnt;i++)
        if(val[i])ins(rt[i],1,n,val[i]);
    }
    void solve(){
        dfs(1);
        cout<<ans<<endl;
    }
    int main(){
        init();
        solve();
    }
    
  • 相关阅读:
    iframe+json
    qw
    MySql数据类型和Java数据类型对应一览
    MyEclipse生成get/set注释
    Redis集群_主从配置
    MyBatis输出sql需要log4j.properties配置
    默认没有创建两次定时实例的
    spring+freemarker+redis
    jquery easyui 扩展验证
    vs2010 安装 Ajax Control Toolkit
  • 原文地址:https://www.cnblogs.com/orzzz/p/8094176.html
Copyright © 2020-2023  润新知