bzoj3702二叉树 线段树合并
3702: 二叉树
Time Limit: 15 Sec Memory Limit: 256 MB
Submit: 600 Solved: 272
[Submit][Status][Discuss]
Description
现在有一棵二叉树,所有非叶子节点都有两个孩子。在每个叶子节点上有一个权值(有n个叶子节点,满足这些权值为1..n的一个排列)。可以任意交换每个非叶子节点的左右孩子。
要求进行一系列交换,使得最终所有叶子节点的权值按照中序遍历写出来,逆序对个数最少。
Input
第一行n
下面每行,一个数x
如果x==0,表示这个节点非叶子节点,递归地向下读入其左孩子和右孩子的信息,
如果x!=0,表示这个节点是叶子节点,权值为x。
Output
一行,最少逆序对个数。
Sample Input
3
0
0
3
1
2
Sample Output
1
HINT
对于100%的数据:2<=n<=200000。
两棵子树交换不影响子树内的值,所以每次只考虑相邻两棵子树怎样放,再考虑上一层怎么放
线段树合并: 开权值线段记录原树中每个节点的子树对应拥有的值,向上合并的时候统计答案
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
#define N 200050
using namespace std;
int n,tot,cnt,v[N*3],rt[N*3],l[N*3],r[N*3],ls[N*20],rs[N*20],sum[N*20];
ll ans,a,b;
void tree(int &x){
x=++tot;
scanf("%d",&v[tot]);
if(v[tot])return;
tree(l[x]);
tree(r[x]);
}
void update(int &u,int l,int r,int p){
if(!u)u=++cnt;sum[u]++;
if(l==r)return;
int mid=l+r>>1;
if(p<=mid)update(ls[u],l,mid,p);
else update(rs[u],mid+1,r,p);
}
int merge(int x,int y){
if(!x)return y;
if(!y)return x;
a+=1ll*sum[ls[x]]*sum[rs[y]];
b+=1ll*sum[rs[x]]*sum[ls[y]];
ls[x]=merge(ls[x],ls[y]);
rs[x]=merge(rs[x],rs[y]);
sum[x]=sum[ls[x]]+sum[rs[x]];
return x;
} void solve(int x){
if(!x)return;
solve(l[x]);solve(r[x]);
if(v[x])return;
a=0;b=0;
rt[x]=merge(rt[l[x]],rt[r[x]]);
ans+=min(a,b);
} int main(){
scanf("%d",&n);
int root;tree(root);
for(int i=1;i<=tot;i++)
if(v[i])update(rt[i],1,n,v[i]);
solve(1);cout<<ans;
return 0;
}
bzoj3702二叉树 线段树合并的更多相关文章
- bzoj3702/bzoj2212 二叉树 (线段树合并)
用线段树记每个子树中包含的数,然后合并的时候算出来逆序对的数量(合并a,b时,就是size[ch[a][1]]*size[ch[b][0]]),来决定这个子树要不要翻转 #include<bit ...
- BZOJ_2212_[Poi2011]Tree Rotations_线段树合并
BZOJ_2212_[Poi2011]Tree Rotations_线段树合并 Description Byteasar the gardener is growing a rare tree cal ...
- BZOJ2212 [Poi2011]Tree Rotations 线段树合并 逆序对
原文链接http://www.cnblogs.com/zhouzhendong/p/8079786.html 题目传送门 - BZOJ2212 题意概括 给一棵n(1≤n≤200000个叶子的二叉树, ...
- hdu6133 Army Formations 线段树合并
给你一棵有n个节点的二叉树,每个节点有一个权值,对于一棵子树u,将u的子树中的节点权值从大到小排序,令sz[u]为子树u的大小, 则ans[u] = 1 * a[1] + 2 * a[2] + ... ...
- BZOJ.2212.[POI2011]Tree Rotations(线段树合并)
题目链接 \(Description\) 给定一棵n个叶子的二叉树,每个叶节点有权值(1<=ai<=n).可以任意的交换两棵子树.问最后顺序遍历树得到的叶子权值序列中,最少的逆序对数是多少 ...
- 2018.07.07 BZOJ2212: Poi2011Tree Rotations(线段树合并)
2212: [Poi2011]Tree Rotations Time Limit: 20 Sec Memory Limit: 259 MB Description Byteasar the garde ...
- 洛谷P3521 [POI2011]ROT-Tree Rotation [线段树合并]
题目传送门 Tree Rotation 题目描述 Byteasar the gardener is growing a rare tree called Rotatus Informatikus. I ...
- BZOJ2212 [Poi2011]Tree Rotations 【线段树合并】
题目链接 BZOJ2212 题解 一棵子树内的顺序不影响其与其它子树合并时的答案,这一点与归并排序的思想非常相似 所以我们只需单独处理每个节点的两棵子树所产生的最少逆序对即可 只有两种情况,要么正序要 ...
- 2017多校第8场 HDU 6133 Army Formations 线段树合并
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6133 题意:给你一棵n个节点的二叉树,每个节点有一个提交任务的时间,每个节点总的提交任务的罚时为:提交 ...
随机推荐
- nyoj 韩信点兵
描述相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排.五人一排.七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了.输入3个非负整数a,b,c ,表示每种队形排尾的人数 ...
- HTML 样式设计
1.自动设置外边距 style="margin:auto auto;"
- JAVA_SE基础——18.方法的递归
方法的递归是指在一个方法的内部调用自身的过程,递归必须要有结束条件,不然就会陷入无限递归的状态,永远无法结束调用,接下来用一个最简单的例子来体现下方法递归,使用递归算法计算自然数之和: public ...
- Python之旅.第三章.函数3.30
一.迭代器 1.什么是迭代?:迭代是一个重复的过程,并且每次重复都是基于上一次的结果而来2.要想了解迭代器到底是什么?必须先了解一个概念,即什么是可迭代的对象?可迭代的对象:在python中,但凡内置 ...
- AngularJS1.X学习笔记11-服务
如果我没记错的话,spring里边有个service层.什么是服务呢?个人理解就是很多地方要用的,可以跨越控制器甚至是跨越模块的工具.AngularJS也为我们提供了服务这种机制,这让我们可以将一些不 ...
- kubernetes入门(10)kubernetes单机安装后 - helloworld
前言 查看端口是否被监听了 ::netstat -tlp |grep 31002 我是用的yum install etcd kubernetes docker vim, 这样装的是1.5.2,不是最新 ...
- Homebrew update error not work on OSX
brew update 错误是这样的 chown: /usr/local: Operation not permitted 然后网上osx 10.11, 10.12的解决方法这样的 The probl ...
- django Form组件
django Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试牛刀 1.创建 ...
- Java:Linux上java -jar xxx.jar命令执行jar包时出现Error: Invalid or corrupt jarfile xxx.jar解决方案
背景: 从ftp上上传jar包到linux上,之后在linux上通过ftp命令下载jar包文件,开始执行Java-jar,一直提示错误:Error: Invalid or corrupt jarfil ...
- hdu-3348 coins---贪心
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3348 题目大意: 给你一个价格,还有面值分别为1,5,10,50,100(单位:毛)纸币的数量,要你 ...