zoukankan      html  css  js  c++  java
  • BZOJ 2212 [Poi2011]Tree Rotations(线段树合并)

    【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=2212

    【题目大意】

      给出一棵二叉树,每个叶节点上有一个权值,现在可以任意交换左右儿子,
      使得逆序对最少,求最少的逆序对数量

    【题解】

      我们发现对于每个非叶节点来说,其贡献值为左右两个儿子的权值树上,
      每个节点想反位置的数量和乘积,比如左儿子的权值树左节点和右儿子权值树的右节点相乘,
      那么我们对于每个节点建立一颗权值线段树,仅保留非0链,
      递归合并这些权值线段树,同时每次将相反位置数量乘积的最小值累加到答案即可

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    using namespace std;
    const int N=400010,M=N*20;
    typedef long long LL;
    int n,a[N],cnt,Root,root[N];
    int Tree[N][2];
    LL Ans,Ans0,Ans1;
    void Read_Tree(int &x){
        x=++cnt;
        scanf("%d",&a[x]);
        if(a[x])return;
        Read_Tree(Tree[x][0]);
        Read_Tree(Tree[x][1]);
    }
    namespace Segment_Tree{
        int tot;
        struct node{int l,r,a,b,sum;}T[M];
        void up(int x){T[x].sum=T[T[x].l].sum+T[T[x].r].sum;}
        int build(int l,int r,int p){
            int x=++tot;
            T[x].a=l; T[x].b=r; T[x].sum=0; 
            if(l==r){T[x].sum=1;return x;}
            int mid=(l+r)>>1;
            if(p<=mid){T[x].l=build(l,mid,p);}
            else{T[x].r=build(mid+1,r,p);}
            return up(x),x;
        }
        int merge(int x,int y){
            if(!x||!y)return x^y;
            Ans0+=(LL)T[T[x].r].sum*(LL)T[T[y].l].sum;
            Ans1+=(LL)T[T[x].l].sum*(LL)T[T[y].r].sum;
            T[x].l=merge(T[x].l,T[y].l);
            T[x].r=merge(T[x].r,T[y].r);
            return up(x),x;
        }
        void dfs(int x){
            if(a[x])return;
            dfs(Tree[x][0]); dfs(Tree[x][1]);
            Ans0=Ans1=0;
            root[x]=merge(root[Tree[x][0]],root[Tree[x][1]]);
            Ans+=min(Ans0,Ans1);
        }
    }
    int main(){
        scanf("%d",&n);
        Read_Tree(Root);
        for(int i=1;i<=cnt;i++)if(a[i]!=0)root[i]=Segment_Tree::build(1,n,a[i]);
        Segment_Tree::dfs(Root);
        printf("%lld
    ",Ans);
        return 0;
    }
  • 相关阅读:
    element ui 表单清空
    element ui 覆盖样式 方法
    element ui 修改表单值 提交无效
    element ui 抽屉里的表单输入框无法修改值
    element ui 抽屉首次显示 闪烁
    css 左侧高度 跟随右侧内容高度 自适应
    PICNUF框架
    elementui 抽屉组件标题 出现黑色边框
    vue 子组件跨多层调用父组件中方法
    vue 编辑table 数据 未点击提交,table里的数据就发生了改变(深拷贝处理)
  • 原文地址:https://www.cnblogs.com/forever97/p/bzoj2212.html
Copyright © 2011-2022 走看看