bzoj 2212: [Poi2011]Tree Rotations
Description
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 . 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), (1< = I < j < = N ) such that(Ai>Aj) in the corona(A1,A2,A3…An). The original tree (on the left) with corona(3,1,2) has two inversions. A single rotation gives a tree (on the right) with corona(1,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的一个排列)。可以任意交换每个非叶子节点的左右孩子。
要求进行一系列交换,使得最终所有叶子节点的权值按照遍历序写出来,逆序对个数最少。
Solution
实现非常巧妙,在线段树合并时可以直接统计
具体思想:
x子树内的逆序对数=左儿子内部的逆序对数+右儿子内部的逆序对数+左右儿子组合的逆序对数
前两项与左右儿子的顺序无关,只需要决策最后一项即可,一路推到根节点即为答案
\(t1+=s[ls[x]]*s[rs[y]]\)
\(t2+=s[rs[x]]*s[ls[y]]\)
在合并时顺便统计两种决策,最后答案加上 \(Min(t1,t2)\)
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=400005;
int root[N],val[N],totnode=0,cnt=1,ls[N*20],rs[N*20],n;
ll ans=0,t1=0,t2=0,s[N*20];int L[N],R[N];
void dfs(int x){
scanf("%d",&val[x]);
if(!val[x]){
L[x]=++cnt;dfs(L[x]);
R[x]=++cnt;dfs(R[x]);
}
}
void ins(int &rt,int l,int r,int sa){
if(!rt)rt=++totnode;
if(l==r){s[rt]=1;return ;}
int mid=(l+r)>>1;
if(sa<=mid)ins(ls[rt],l,mid,sa);
else ins(rs[rt],mid+1,r,sa);
s[rt]=s[ls[rt]]+s[rs[rt]];
}
int merge(int x,int y){
if(!x)return y;if(!y)return x;
t1+=s[ls[x]]*s[rs[y]];
t2+=s[rs[x]]*s[ls[y]];
ls[x]=merge(ls[x],ls[y]);
rs[x]=merge(rs[x],rs[y]);
s[x]=s[ls[x]]+s[rs[x]];
return x;
}
void solve(int x){
if(!x)return ;
solve(L[x]);solve(R[x]);
if(!val[x]){
t1=0;t2=0;
root[x]=merge(root[L[x]],root[R[x]]);
ans+=Min(t1,t2);
}
}
void work()
{
scanf("%d",&n);
dfs(1);
for(int i=1;i<=cnt;i++)
if(val[i])ins(root[i],1,n,val[i]);
solve(1);
printf("%lld\n",ans);
}
int main(){work();return 0;}
bzoj 2212: [Poi2011]Tree Rotations的更多相关文章
- BZOJ 2212: [Poi2011]Tree Rotations( 线段树 )
线段树的合并..对于一个点x, 我们只需考虑是否需要交换左右儿子, 递归处理左右儿子. #include<bits/stdc++.h> using namespace std; #defi ...
- [BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】
题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换 ...
- BZOJ 2212 [Poi2011]Tree Rotations(线段树合并)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2212 [题目大意] 给出一棵二叉树,每个叶节点上有一个权值,现在可以任意交换左右儿子, ...
- bzoj 2212 : [Poi2011]Tree Rotations (线段树合并)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2212 思路:用线段树合并求出交换左右儿子之前之后逆序对的数量,如果数量变小则交换. 实现 ...
- BZOJ.2212.[POI2011]Tree Rotations(线段树合并)
题目链接 \(Description\) 给定一棵n个叶子的二叉树,每个叶节点有权值(1<=ai<=n).可以任意的交换两棵子树.问最后顺序遍历树得到的叶子权值序列中,最少的逆序对数是多少 ...
- 2212: [Poi2011]Tree Rotations
2212: [Poi2011]Tree Rotations https://www.lydsy.com/JudgeOnline/problem.php?id=2212 分析: 线段树合并. 首先对每个 ...
- 【BZOJ】2212: [Poi2011]Tree Rotations
题意 给一棵\(n(1 \le n \le 200000)\)个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少. 分析 可以发现如果交换非叶结点的左右子树,对子树内的交换无影响, ...
- Bzoj P2212 [Poi2011]Tree Rotations | 线段树合并
题目链接 通过观察与思考,我们可以发现,交换一个结点的两棵子树,只对这两棵子树内的节点的逆序对个数有影响,对这两棵子树以外的节点是没有影响的.嗯,然后呢?(っ•̀ω•́)っ 然后,我们就可以对于每一个 ...
- BZOJ2212: [Poi2011]Tree Rotations
2212: [Poi2011]Tree Rotations Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 391 Solved: 127[Submi ...
随机推荐
- localhost访问不了的解决方法
c:\windows\system32\drivers\etc\hosts 用记事本打开,加入一行 127.0.0.1 localhost
- OO前三次作业总结
一.第一次作业 1.程序设计分析  图1 第一次作业类图 的请求,会从head开始,依次往tail传递. pipeline采用了链表结构,he ...
- 电脑上的安卓系统——PhoenixOS浅度体验
前言 其实这篇关于PhoenixOS的浅度评测在几个月前就准备发了,当时是刚看到新闻说Android 7.0 x86的正式版刚刚发布,于是就下载来安装一番,结果.....体验极差= =,只能用这4个字 ...
- linux系统环境与文件权限
默认有6个命令交互通道和一个图形界面交互通道,默认进入到的是图形界面通道 命令交互模式切换:ctrl+alt+f1---f6 图形交互界面 ctrl+alt+f7 1.图形界面交互模式 - termi ...