洛谷P3521 [POI2011]ROT-Tree Rotation [线段树合并]
Tree Rotation
题目描述
Byteasar the gardener is growing a rare tree called Rotatus Informatikus.
It has some interesting features:
The tree consists of straight branches, bifurcations and leaves.
The trunk stemming from the ground is also a branch.
Each branch ends with either a bifurcation or a leaf on its top end.
Exactly two branches fork out from a bifurcation at the end of a branch - the left branch and the right branch.
Each leaf of the tree is labelled with an integer from the range 1..n1..n.
The labels of leaves are unique.
With some gardening work, a so called rotation can be performed on any bifurcation, swapping the left and right branches that fork out of it.
The corona of the tree is the sequence of integers obtained by reading the leaves' labels from left to right.
Byteasar is from the old town of Byteburg and, like all true Byteburgers, praises neatness and order.
He wonders how neat can his tree become thanks to appropriate rotations.
The neatness of a tree is measured by the number of inversions in its corona, i.e. the number of pairs (i,j)(i,j), 1\le i<j\le n1≤i<j≤n such that a_i>a_jai>aj in the corona a_1,a_2,\cdots,a_na1,a2,⋯,an.
The original tree (on the left) with corona 3,1,23,1,2 has two inversions.
A single rotation gives a tree (on the right) with corona 1,3,21,3,2, which has only one inversion.
Each of these two trees has 5 branches.
Write a program that determines the minimum number of inversions in the corona of Byteasar's tree that can be obtained by rotations.
给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少。
输入输出格式
输入格式:
In the first line of the standard input there is a single integer nn(2\le n\le 200\ 0002≤n≤200 000) that denotes the number of leaves in Byteasar's tree.
Next, the description of the tree follows.
The tree is defined recursively:
if there is a leaf labelled with pp (1\le p\le n1≤p≤n) at the end of the trunk (i.e., the branch from which the tree stems),then the tree's description consists of a single line containing a single integer pp
if there is a bifurcation at the end of the trunk, then the tree's description consists of three parts:
- the first line holds a single number 00
- then the description of the left subtree follows (as if the left branch forking out of the bifurcation was its trunk),
- and finally the description of the right subtree follows (as if the right branch forking out of the bifurcation was its trunk).
In tests worth at least 30% of the points it additionally holds that n\le 5\ 000n≤5 000.
输出格式:
In the first and only line of the standard output a single integer is to be printed:
the minimum number of inversions in the corona of the input tree that can be obtained by a sequence of rotations.
输入输出样例
3
0
0
3
1
2
1
说明
给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少。
分析:
线段树合并的模板题。
线段树合并是一种常用的技巧,一般是对权值线段树合并,方法也很简单,将两棵线段树上的权值相加即可,一般用于权值线段树。
另外关于这题的答案统计,在合并的过程中只要把子节点的线段树放在左边,当前节点的线段树放在右边,然后子节点的左边与当前节点的右边相乘得到的就是不交换子节点得到的答案,子节点的右边与当前节点的左边相乘得到的就是交换子节点得到的答案。(正确性易证)
Code:
//It is made by HolseLee on 15th Oct 2018
//Luogu.org P3521
#include<bits/stdc++.h>
using namespace std; typedef long long ll;
const int N=1e7+;
int n,tot,ls[N],rs[N],seg[N];
ll ans,ret1,ret2; inline int read()
{
char ch=getchar(); int num=; bool flag=false;
while( ch<'' || ch>'' ) {
if( ch=='-' ) flag=false; ch=getchar();
}
while( ch>='' && ch<='' ) {
num=num*+ch-''; ch=getchar();
}
return flag ? -num : num;
} int build(int l,int r,int x)
{
seg[++tot]=;
if( l==r ) return tot;
int mid=(l+r)>>;
int rt=tot;
if( x<=mid ) ls[rt]=build(l,mid,x);
else rs[rt]=build(mid+,r,x);
return rt;
} int merge(int l,int r,int x,int y)
{
if( !x || !y ) return x+y;
if( l==r ) {
seg[++tot]=seg[x]+seg[y];
return tot;
}
int rt=++tot, mid=(l+r)>>;
ret1+=(ll)seg[ls[x]]*seg[rs[y]];
ret2+=(ll)seg[rs[x]]*seg[ls[y]];
ls[rt]=merge(l,mid,ls[x],ls[y]);
rs[rt]=merge(mid+,r,rs[x],rs[y]);
seg[rt]=seg[ls[rt]]+seg[rs[rt]];
return rt;
} int get()
{
int tmp=read();
if( tmp ) return build(,n,tmp);
int now=merge(,n,get(),get());
ans+=min(ret1,ret2);
ret1=ret2=;
return now;
} int main()
{
n=read();
get(); printf("%lld\n",ans);
return ;
}
洛谷P3521 [POI2011]ROT-Tree Rotation [线段树合并]的更多相关文章
- BZOJ2212【POI2011】ROT:Tree Rotation 线段树合并
题意: 给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求叶子遍历序的逆序对最少. 分析: 求逆序对我们可以想到权值线段树,所以我们对每个点建一颗线段树(为了避免空间爆炸,采 ...
- 洛谷P3066 [USACO12DEC]逃跑的Barn (线段树合并)
题目描述It's milking time at Farmer John's farm, but the cows have all run away! Farmer John needs to ro ...
- 洛谷P1600 天天爱跑步(线段树合并)
小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 nn ...
- 洛谷P3224 [HNOI2012]永无乡(线段树合并+并查集)
题目描述 永无乡包含 nnn 座岛,编号从 111 到 nnn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nnn 座岛排名,名次用 111 到 nnn 来表示.某些岛之间由巨大的桥连接, ...
- 洛谷 P2824 [HEOI2016/TJOI2016]排序 (线段树合并)
(另外:题解中有一种思路很高妙而且看上去可以适用一些其他情况的离线方法) 线段树合并&复杂度的简单说明:https://blog.csdn.net/zawedx/article/details ...
- P3521 [POI2011]ROT-Tree Rotations (线段树合并)
P3521 [POI2011]ROT-Tree Rotations 题意: 给你一颗树,只有叶子节点有权值,你可以交换一个点的左右子树,问你最小的逆序对数 题解: 线段树维护权值个个数即可 然后左右子 ...
- loj2163 / bzoj2212 / P3521 [POI2011]ROT-Tree Rotations(线段树合并)
P3521 [POI2011]ROT-Tree Rotations loj2163 [POI2011]ROT-Tree Rotations(数据加强) (loj的数据套了个fread优化才过...) ...
- 洛谷P4556 雨天的尾巴(线段树合并)
洛谷P4556 雨天的尾巴 题目链接 题解: 因为一个点可能存放多种物品,直接开二维数组进行统计时间.空间复杂度都不能承受.因为每一个点所拥有的物品只与其子树中的点有关,所以可以考虑对每一个点来建立一 ...
- P3521 [POI2011]ROT-Tree Rotations(线段树合并)
一句话题意(不用我改了.....):给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少. ......这题输入很神烦呐... 给你一棵二叉树的dfs序 ...
- BZOJ_2212_[Poi2011]Tree Rotations_线段树合并
BZOJ_2212_[Poi2011]Tree Rotations_线段树合并 Description Byteasar the gardener is growing a rare tree cal ...
随机推荐
- stl空间配置器简介
1. 符合STL标准的空间配器接口 STL是c++中使用非常广泛的一个标准库,它包含各种有用的容器.而空间配置器作为STL各种容器的背后的核心,负责容器内部内存的分配和释放.不过空间配置器可以分配的也 ...
- SHA-1(安全哈希算法实现)
如题,不知道sha-1的自己百度吧. #include <iostream> #include <vector> //定义vector数组 #include <strin ...
- Linux学习5-线程
线程 1.1什么是线程? 在一个程序中的多个执行路线就叫做线程(thread).更准确的定义是:线程是一个进程内部的一个控制序列. 要搞清楚fork系统调用和创建新线程之间的区别.当进程执行for ...
- python正则表达式-re模块的爱恨情仇
利用python的re模块,使用正则表达式对字符串进行处理 # 编辑者:闫龙 import re restr = "abccgccc123def456ghi789jgkl186000&quo ...
- JavaScript常用数组方法
JavaScript数组方法有以下这些: forEach() 方法对数组的每一个元素执行一次提供的函数. map() 方法创建一个新数组,其结果是该数组都执行一次函数,原函数保持不变. filter( ...
- 关于注入抽象类报could not autowire field的问题
昨天工作中遇到了一个很奇葩的问题,之前一直都没考虑过抽象类这块,一直用的注入接口实现类: 先看下错误: 因为在类中注入了一个抽象类,之前只有一个继承子类,所以没问题,这里要说一下抽象类的实例化: 抽象 ...
- curator框架的使用以及实现分布式锁等应用与zkclient操作zookeeper,简化复杂原生API
打开zookeeper集群 先体会一下原生API有多麻烦(可略过): //地址 static final String ADDR = "192.168.171.128:2181,192.16 ...
- python基础之命名空间
前言 命名空间通俗的理解就是对象或变量的作用范围,在python中分为局部命令空间.模块命名空间和build-in全局命名空间. 局部命名空间 局部命名空间即在一个函数或一个类中起作用的变量或引用的字 ...
- python-windows下将单个py文件生成exe
突然要生成一个exe给其他人用.紧急搜索下了 命令行参数获取用如下方法 from sys import argv base64path = argv[1] argv这个元组就是你的参数列表了,同C一样 ...
- 深度学习在美团点评推荐平台排序中的应用&& wide&&deep推荐系统模型--学习笔记
写在前面:据说下周就要xxxxxxxx, 吓得本宝宝赶紧找些广告的东西看看 gbdt+lr的模型之前是知道怎么搞的,dnn+lr的模型也是知道的,但是都没有试验过 深度学习在美团点评推荐平台排序中的运 ...