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 ...
随机推荐
- Django 个性化管理员站点
from django.contrib import admin # Register your models here. from .models import Moment class Momen ...
- edittext实现自动查询,刷新listview
mEdittextqueryvalue.addTextChangedListener(new TextWatcher() { @Override pub ...
- RxSwift 函数响应式编程
Max 在 Boston 上学,在 San Francisco 工作,是一名软件工程师及创业者.当他还在高中的时候就在一家创业公司工作了,他非常喜欢使用 iOS.Android 以及 JavaScri ...
- 【iOS】swift-Binary operator '|' cannot be applied to two UIViewAutoresizing operands
let view = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 568)) addSubview(view) view.autoresi ...
- emqtt 试用(三)mqtt 知识
一.概念 MQTT 协议客户端库: https://github.com/mqtt/mqtt.github.io/wiki/libraries 例如,mosquitto_sub/pub 命令行发布订阅 ...
- SpringBoot的RestController vs @ResponseBody + @Controller
@Controller和@RestController的区别?官方文档:@RestController is a stereotype annotation that combines @Respon ...
- Spring知识点回顾(04)el 和资源使用
注入普通字符 注入操作系统属性 注入表达式运算结果 注入其他bean属性 注入文件内容 注入网址内容 注入属性文件
- 阿里云API网关(18)请求报文和响应报文
网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...
- Spring Security 入门(1-3-3)Spring Security - logout 退出登录
要实现退出登录的功能我们需要在 http 元素下定义 logout 元素,这样 Spring Security 将自动为我们添加用于处理退出登录的过滤器 LogoutFilter 到 FilterCh ...
- C++中友元
一.友元分为两种 1.友元函数 2.友元类 二.解析比较好的博客:http://www.cnblogs.com/BeyondAnyTime/archive/2012/06/04/2535305.htm ...