题目传送门

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.

输入输出样例

输入样例#1:

3
0
0
3
1
2
输出样例#1:

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 [线段树合并]的更多相关文章

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

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

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

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

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

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

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

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

  5. 洛谷 P2824 [HEOI2016/TJOI2016]排序 (线段树合并)

    (另外:题解中有一种思路很高妙而且看上去可以适用一些其他情况的离线方法) 线段树合并&复杂度的简单说明:https://blog.csdn.net/zawedx/article/details ...

  6. P3521 [POI2011]ROT-Tree Rotations (线段树合并)

    P3521 [POI2011]ROT-Tree Rotations 题意: 给你一颗树,只有叶子节点有权值,你可以交换一个点的左右子树,问你最小的逆序对数 题解: 线段树维护权值个个数即可 然后左右子 ...

  7. loj2163 / bzoj2212 / P3521 [POI2011]ROT-Tree Rotations(线段树合并)

    P3521 [POI2011]ROT-Tree Rotations loj2163 [POI2011]ROT-Tree Rotations(数据加强) (loj的数据套了个fread优化才过...) ...

  8. 洛谷P4556 雨天的尾巴(线段树合并)

    洛谷P4556 雨天的尾巴 题目链接 题解: 因为一个点可能存放多种物品,直接开二维数组进行统计时间.空间复杂度都不能承受.因为每一个点所拥有的物品只与其子树中的点有关,所以可以考虑对每一个点来建立一 ...

  9. P3521 [POI2011]ROT-Tree Rotations(线段树合并)

    一句话题意(不用我改了.....):给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少. ......这题输入很神烦呐... 给你一棵二叉树的dfs序 ...

  10. BZOJ_2212_[Poi2011]Tree Rotations_线段树合并

    BZOJ_2212_[Poi2011]Tree Rotations_线段树合并 Description Byteasar the gardener is growing a rare tree cal ...

随机推荐

  1. ECMAScript6语法检查规范错误信息说明

    项目中使用ECMAScript6的时候经查会使用语法检查,下面是常见错误信息的汇总: “Missing semicolon.” : “缺少分号.”, “Use the function form of ...

  2. Jekins - Hello world,Jekins + Maven + Git + Tomcat 的简单应用

    Java Web 工程 新建一个简单的 Java Web 工程,并提交至 GitHub,可参考 Eclipse 提交工程至 GitHub 下载 jekins.war 在 http://mirrors. ...

  3. An Insight to References in C++

    [An Insight to References in C++] 引用的本质是常指针.占用的内存和指针一样. 参考:http://www.codeproject.com/Articles/13363 ...

  4. c++程序设计中的函数重载

    函数重载的意思是在一个作用域内(命名空间内)定义了某个或某些具有相同名称的函数,但是他们的参数列表和定义(实现)不相同,如果相同的话,就没啥意义了.当调用一个重载函数时,编译器会通过所使用的参数类型. ...

  5. 【CC2530强化实训02】普通延时函数实现按键的长按与短按

    [CC2530强化实训02]普通延时函数实现按键的长按与短按 [题目要求]      用一个按键实现单击与双击的功能已经是很多嵌入式产品的常用手法.使用定时器的间隔定时来计算按键按下的时间是通用的做法 ...

  6. const与指针

    C++中const与指针 1.常指针: ; int * const pInt = &x; 其中PInt是常指针,pInt的值无法改变,但其指向的内容可以改变. 2.指向常量的指针 有两种写法: ...

  7. C/S模式和B/S模式

    C/S模式和B/S模式 1.C/S模式(Client/Server,客户机/服务器模式) 如QQ 暴风影音,PPlive等应用软件都是C/S模式 是一种软件系统结构的一种,C/S模式是基于企业内部网络 ...

  8. web项目打包后在代码中获取资源文件

    在web项目里面,有时代码里面需要引用一些自定义的配置文件,这些配置文件如果放在类路径下,项目经过打包后使用的相对路径也会发生变化,所以以下给出了三种解决方案. 一.properties下配置 在类路 ...

  9. win7 64位mysql安装及navicat 解压版

    教程:http://jingyan.baidu.com/article/f3ad7d0ffc061a09c3345bf0.html Mysql修改设置root密码的命令及方法:http://jingy ...

  10. idea开发工具下载安装教程

    我用这款工具主要用于java开发 在安装这个工具之前需要配置java的环境 java的jdk环境配置 jdk:1.8 jdk官网下载链接 --->点我 进入之后,下拉  选择 jdk1.8版本 ...