题意:给定一颗有 n 个叶节点的二叉树。每个叶节点都有一个权值pi​(注意,根不是叶节点),所有叶节点的权值构成了一个1∼n 的排列。对于这棵二叉树的任何一个结点,保证其要么是叶节点,要么左右两个孩子都存在。现在你可以任选一些节点,交换这些节点的左右子树。在最终的树上,按照先序遍历遍历整棵树并依次写下遇到的叶结点的权值构成一个长度为 n的排列,你需要最小化这个排列的逆序对数。

输入格式:第一行是一个整数 n,表示树的叶节点个数。接下来若干行,使用递归的形式来读入这棵树,读入任意一个子树的信息时,初始时读入其根节点。对于一个结点 u,首先有一行一个整数 x。若 x≠0,则表示 u 是一个叶节点,其权值为 x。若 x = 0,则表示 u 不是叶节点,则接下来若干行读入其左子树信息,左子树读入结束后接下来若干行读入其右子树信息。

输出格式:输出一行一个整数表示最小的逆序对数。

分析:假设当前点的左右儿子分别为ls,rs,很容易发现,交换以这两个结点为根节点的子树,并不会影响他们的祖宗交换时逆序对的个数。所以我们可以考虑每一层贪心地进行交换,此时局部最优即全局最优。同时,对于区间[L,R],设其中点为mid,我们只需要考虑这样的逆序对(x,y),满足L ≤ x ≤ mid,mid+1 ≤ y ≤ R即可,并不需要考虑在同一个子树中的逆序对数量。由于这是权值线段树,那么逆序对其实很好统计,对于两颗线段树代表同一段区间的两个节点,考虑交换与不交换两种情况,分别取左、右部分或者右、左部分统计逆序对个数。最后取最小值就可以了。

#include<cstdio>
const int maxn = 2e5+5; typedef long long ll; int n, x, cnt;
int sum[maxn << 5], ls[maxn << 5], rs[maxn << 5];
ll ans, s1, s2;
int rt[maxn]; inline ll min(ll a, ll b) { return a < b ? a : b; } void ins(int &u, int l, int r, int pos){
if(!u) u = ++cnt; ++sum[u];
if(l == r) { return ; }
int mid = (l + r) >> 1;
if(pos <= mid) ins(ls[u], l, mid, pos);
else ins(rs[u], mid + 1, r, pos);
} void merge(int &a, int b){
if(!a || !b) { a = a | b; return ;}
sum[a] += sum[b];
s1 += 1LL * sum[ls[a]] * sum[rs[b]];
s2 += 1LL * sum[rs[a]] * sum[ls[b]];
merge(ls[a], ls[b]);
merge(rs[a], rs[b]);
sum[a] = sum[ls[a]] + sum[rs[a]];
} int dfs(){
scanf("%d", &x);
if(x) return ins(rt[x], 1, n, x), rt[x];
else{
int ls, rs;
ls = dfs(), rs = dfs();
s1 = s2 = 0;
merge(ls, rs);
ans += min(s1, s2);
return ls;
}
} int main(){
scanf("%d", &n);
dfs();
printf("%lld", ans);
return 0;
}

洛谷3521 [POI2011]ROT-Tree Rotations(线段树合并)的更多相关文章

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

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

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

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

  3. BZOJ2212 [Poi2011]Tree Rotations 线段树合并 逆序对

    原文链接http://www.cnblogs.com/zhouzhendong/p/8079786.html 题目传送门 - BZOJ2212 题意概括 给一棵n(1≤n≤200000个叶子的二叉树, ...

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

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

  5. BZOJ2212【POI2011】ROT:Tree Rotation 线段树合并

    题意: 给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求叶子遍历序的逆序对最少. 分析: 求逆序对我们可以想到权值线段树,所以我们对每个点建一颗线段树(为了避免空间爆炸,采 ...

  6. Bzoj P2212 [Poi2011]Tree Rotations | 线段树合并

    题目链接 通过观察与思考,我们可以发现,交换一个结点的两棵子树,只对这两棵子树内的节点的逆序对个数有影响,对这两棵子树以外的节点是没有影响的.嗯,然后呢?(っ•̀ω•́)っ 然后,我们就可以对于每一个 ...

  7. 洛谷P3066 [USACO12DEC]逃跑的Barn (线段树合并)

    题目描述It's milking time at Farmer John's farm, but the cows have all run away! Farmer John needs to ro ...

  8. 洛谷P1600 天天爱跑步(线段树合并)

    小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 nn ...

  9. 洛谷P3224 [HNOI2012]永无乡(线段树合并+并查集)

    题目描述 永无乡包含 nnn 座岛,编号从 111 到 nnn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nnn 座岛排名,名次用 111 到 nnn 来表示.某些岛之间由巨大的桥连接, ...

  10. [bzoj2212]Tree Rotations(线段树合并)

    解题关键:线段树合并模板题.线段树合并的题目一般都是权值线段树,因为结构相同,求逆序对时,遍历权值线段树的过程就是遍历所有mid的过程,所有能求出所有逆序对. #include<iostream ...

随机推荐

  1. 《CUDA编程:基础与实践》读书笔记(1):CUDA编程基础

    1. GPU简介 GPU与CPU的主要区别在于: CPU拥有少数几个快速的计算核心,而GPU拥有成百上千个不那么快速的计算核心. CPU中有更多的晶体管用于数据缓存和流程控制,而GPU中有更多的晶体管 ...

  2. EXP 一款 Java 插件化热插拔框架

    EXP 一款 Java 插件化热插拔框架 前言 多年以来,ToB 的应用程序都面临定制化需求应该怎么搞的问题. 举例,大部分本地化软件厂家,都有一个标准程序,这个程序支持大部分企业的功能需求,但面对世 ...

  3. SpringBoot+Mybatis-Plus+Mysql的保姆级搭建

    本文通过简单的示例代码和说明,让读者能够了解Mybatis-Plus+Mysql的简单使用 必须说明的是,本文有部分内容是为了后续的微服务写的,所以如果只想用Mybatis-Plus的话,直接使用ba ...

  4. Spring Cloud OpenFeign 的使用及踩坑指南

    目录 Feign 和OpenFeign Feign OpenFeign openFeign的优势 OpenFeign应用 1. 导入依赖 2. 使用 3. 日志配置 4. 数据压缩 OpenFeign ...

  5. jQuery Ajax执行顺序问题

    代码如下: $(document).ready(function () { var res; $.ajax({ type: 'post', url: 'GridDemo.aspx/PlaceOrder ...

  6. 【python技巧】替换文件中的某几行

    [python技巧]替换文件中的某几行 1. 背景描述 最近在写一个后端项目,主要的操作就是根据用户的前端数据,在后端打开项目中的代码文件,修改对应位置的参数,因为在目前的后端项目中经常使用这个操作, ...

  7. Web项目如何配置Eslint

    介绍 ESLint 是一个根据方案识别并报告 ECMAScript/JavaScript 代码问题的工具,其目的是使代码风格更加一致并避免错误.在很多地方它都与 JSLint 和 JSHint 类似, ...

  8. Linux/Unix-CPU-SuperPI-Unixbench性能测试

    测试服务器CPU单核及多核SuperPI圆周率测试real和user值,SuperPI是利用CPU的浮点运算能力来计算出π(圆周率),测试系统稳定性和测试CPU计算完后特定位数圆周率所需的时间:及Un ...

  9. IDEA2019 Debug傻瓜式上手教程

      Step Into (F7):步入,如果当前行有方法,可以进入方法内部,一般用于进入自定义方法内,不会进入官方类库的方法.   Force Step Into (Alt + Shift + F7) ...

  10. RPM软件包:Red HatPackage Manager,RPM

    RPM软件包是按照GPL条款发行在各个linux版本上使用. 用途 可以安装.删除.升级.刷新和管理RPM软件包 通过RPM软件包管理能知道软件包包含哪些文件,也能知道系统中的某个文件属于哪个RPM软 ...