题目链接: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. Advertising.csv

    TV,radio,newspaper,sales1,230.1,37.8,69.2,22.12,44.5,39.3,45.1,10.43,17.2,45.9,69.3,9.34,151.5,41.3, ...

  2. perl trick

    一.die if以及文件的操作 #!/usr/bin/perl -w use strict; die "USAGE:\n\tperl $0 <><><>\ ...

  3. 【.net】The source was not found, but some or all event logs could not be searched

    1.案发现场: 注册服务的时候 2.解决方案: 用管理员身份运行CMD,再注册服务: I had to run Command Prompt with Administrator Rights.

  4. oracle数据泵导入导出命令

    1.在PL/SQL的界面,找到Directories文件夹,找到目录文件的路径 2.通过SSH进入服务器 找到相应的路径 cd /u01/oracle/dpdir 输入指令 df -h   查看资源使 ...

  5. C语言复习---找出一个二维数组的鞍点

    前提: 求任意的一个m×n矩阵的鞍点——鞍点是指该位置上的元素在该行上为最大.在该列上为最小, 矩阵中可能没有鞍点,但最多只有一个鞍点. m.n(<=m<=.<=n<=)及矩阵 ...

  6. vue-获取dom节点

    获取dom节点可以用ref属性,这个属性就是来获取dom对象的.看代码  这个属性就相当于给这个标签起了一个id样的东西 <input type="text" ref=&qu ...

  7. springMVC的参数检验

    先说应用场景,比如说前台传来一个参数,我们肯定得在后台判断一下,比如id不能为空了,电话号码不能少于11位了等等.如果在service层一个一个判断岂不是要累死个人.代码也不简洁,这时候我们肯定会想到 ...

  8. UNIX网络编程中的字节序问题

    1.inet_pton 函数原型: inet_pton:将“点分十进制” -> “二进制整数” int inet_pton(int af, const char *src, void *dst) ...

  9. python 线程(其他方法,队列,线程池,协程 greenlet模块 gevent模块)

    1.线程的其他方法 from threading import Thread,current_thread import time import threading def f1(n): time.s ...

  10. jquery validate 详解一

    原文:http://blog.sina.com.cn/s/blog_608475eb0100h3h1.html jQuery校验官网地址:http://bassistance.de/jquery-pl ...