题目链接:https://cn.vjudge.net/contest/287725#problem/B

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

具体思路:首先说一下对逆序对的处理。2431的逆序数是4((2,1),(4,3),(4,3),(3,1))。但是两个for循环处理肯定是不行的,我们可以通过线段树来求出逆序对数,每插入一个数,就先判断一个这个数在线段树上后面有多少个数就可以了。

第一次插入2,后面没有数,此时逆序对数为0。

第二次插入4,后面没有数,此时的逆序对数为0.

第三次插入3,后面有2这个数,此时的逆序对数为1。

第四次插入1,后米娜有2,3,4这三个数,此时的逆序对数为1+3=4。

然后再就是对于题目中所说的交换操作了。在线段树中每一个节点的逆序对数等于这个节点的左孩子的逆序对数+右孩子的逆序对数+后面的树中的逆序对数

如果是交换当期节点的左右孩子,当前这个点的逆序对数等于左孩子中大于等于当当前节点值的个数*右孩子中小于等于当前节点值的个数。

如果不交换的话,当前这个点的逆序对数等于左孩子中小于等于当前节点值的个数*右孩子中小于等于当前节点值的个数。

ch数组代表的是当前这个节点在初始二叉树中左孩子和右孩子的编号。

cont代表的数当前在线段树上的编号的贡献

le代表的是当前节点左孩子在线段树的编号

ri代表的是当前节点右孩子在线段树的编号

AC代码:

 #include<bits/stdc++.h>
using namespace std;
# define ll long long
const int maxn = 4e6+;
const int mod =1e6;
# define LL_inf 0x3f3f3f3f3f3f3f
ll n,root,ans,t1,t2;
ll num1,num2;
ll ch[maxn][];
ll cont[maxn];
ll le[maxn],ri[maxn],father[maxn];
void up(ll x){
cont[x]=cont[le[x]]+cont[ri[x]];
}
void update(ll &x,ll val,ll l,ll r){
if(!x)x=++num2;//如果之前出现过就不需要在新建节点了
if(l==r){
cont[x]=;
return ;
}
ll mid=l+r>>;
if(val<=mid)update(le[x],val,l,mid);
else update(ri[x],val,mid+,r);
up(x);
}
void dfs(ll &x){
x=++num1;
ll tmp;
scanf("%lld",&tmp);
if(!tmp){
dfs(ch[x][]);
dfs(ch[x][]);
}
else update(father[x],tmp,,n);
}
ll emerge(ll u,ll v){
if(!u)return v;
if(!v)return u;
t1+=(cont[le[u]]*cont[ri[v]]);
t2+=(cont[le[v]]*cont[ri[u]]);
le[u]=emerge(le[u],le[v]);
ri[u]=emerge(ri[u],ri[v]);
up(u);
return u;
}
void solve(ll x){
if(!ch[x][])return ;
solve(ch[x][]);
solve(ch[x][]);
t1=,t2=;
father[x]=emerge(father[ch[x][]],father[ch[x][]]);//注意这个是father
ans+=min(t1,t2);
}
int main(){
scanf("%lld",&n);
dfs(root);
solve(root);
printf("%lld\n",ans);
}

B - Tree Rotations HYSBZ - 2212 (线段树合并)的更多相关文章

  1. 【bzoj2212】[Poi2011]Tree Rotations 权值线段树合并

    原文地址:http://www.cnblogs.com/GXZlegend/p/6826614.html 题目描述 Byteasar the gardener is growing a rare tr ...

  2. 【bzoj1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+权值线段树合并

    题目描述 求一张图的严格次小生成树的边权和,保证存在. 输入 第一行包含两个整数N 和M,表示无向图的点数与边数. 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z ...

  3. [学习笔记]dsu on a tree(如何远离线段树合并)

    https://www.zybuluo.com/ysner/note/1318613 背景 这玩意来源于一种有局限性的算法. 有一种广为人知的,树上离线维护子树信息的做法. (可以参照luogu360 ...

  4. [BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】

    题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换 ...

  5. bzoj 2212 : [Poi2011]Tree Rotations (线段树合并)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2212 思路:用线段树合并求出交换左右儿子之前之后逆序对的数量,如果数量变小则交换. 实现 ...

  6. BZOJ.2212.[POI2011]Tree Rotations(线段树合并)

    题目链接 \(Description\) 给定一棵n个叶子的二叉树,每个叶节点有权值(1<=ai<=n).可以任意的交换两棵子树.问最后顺序遍历树得到的叶子权值序列中,最少的逆序对数是多少 ...

  7. 【BZOJ2212】[Poi2011]Tree Rotations 线段树合并

    [BZOJ2212][Poi2011]Tree Rotations Description Byteasar the gardener is growing a rare tree called Ro ...

  8. bzoj2212[Poi2011]Tree Rotations [线段树合并]

    题面 bzoj ans = 两子树ans + min(左子在前逆序对数, 右子在前逆序对数) 线段树合并 #include <cstdio> #include <cstdlib> ...

  9. 【BZOJ2212】[POI2011]Tree Rotations (线段树合并)

    题解: 傻逼题 启发式合并线段树里面查$nlog^2$ 线段树合并顺便维护一下$nlogn$ 注意是叶子为n 总结点2n 代码: #include <bits/stdc++.h> usin ...

随机推荐

  1. linux less对文件内容进行搜索

    [ 可以先用 less 文件名 来打开文件, 然后可以按回车,打开底部命令输入行(即出现一个冒号的位置), 然后可以使用  键盘上的 home 键跳到文件开始,end键跳到最后,PgUp向前翻页,Pg ...

  2. HDU 5965 扫雷

    扫雷游戏是晨晨和小璐特别喜欢的智力游戏,她俩最近沉迷其中无法自拔. 该游戏的界面是一个矩阵,矩阵中有些格子中有一个地雷,其余格子中没有地雷. 游戏中,格子可能处于己知和未知的状态.如果一个己知的格子中 ...

  3. nginx根据cookie分流

    转载互联网 nginx根据cookie分流众所周知,nginx可以根据url path进行分流,殊不知对于cookie分流也很强大,同时这也是我上篇提到的小流量实验的基础. 二话不说,先看需求,两台服 ...

  4. 【优秀的Sketch插件】PaintCode for Sketch for Mac 1.1

    [简介] PaintCode for Sketch 是一款结合了PaintCode和Sketch两款软件强大功能的插件,今天和大家分享最新的1.1版本,支持Sketch 40+版本,这个插件能够让你的 ...

  5. 流畅的python--2 序列构成的数组

    我们把文本.列表和表格叫做数据火车...FOR命令通常能作用于数据火车上.      ---ABC Programmer's Handbook 不管是哪种数据结构,字符串.列表.字节序列.数组.XML ...

  6. kernel(一)编译体验

    目录 打补丁 配置 总结 配置方式 配置体验 配置详解 Makefile解析 子目录的Makefile 架构下面的Makefile 顶层Makefile Make解析 编译 链接 链接脚本 烧写内核 ...

  7. java io系列22之 FileReader和FileWriter

    FileReader 是用于读取字符流的类,它继承于InputStreamReader.要读取原始字节流,请考虑使用 FileInputStream.FileWriter 是用于写入字符流的类,它继承 ...

  8. python 面向对象(四)反射

    ####################总结########## 1. isinstance: 判断xxx是否是xxx类型的(向上判断) type: 返回xx对象的数据类型 issubclass: 判 ...

  9. Linux记录-文件格式

    yum -y install dos2unix dos2unix filename

  10. GridView固定行宽,自动换行,鼠标放在Table的Tr上变色

    //固定行宽table-layout:fixed;//自动换行word-break :break-all;word-wrap:break-wordGridView.Attributes.Add(&qu ...