线段树合并(【POI2011】ROT-Tree Rotations)

题意

现在有一棵二叉树,所有非叶子节点都有两个孩子。在每个叶子节点上有一个权值(有nn个叶子节点,满足这些权值为1…n1…n的一个排列)。可以任意交换每个非叶子节点的左右孩子。

要求进行一系列交换,使得最终所有叶子节点的权值按照前序遍历序写出来,逆序对个数最少。

解法

我们对每一个叶子节点建立一颗权值线段树,然后,我们考虑将两个叶子节点上的线段树合并起来,然后我们考虑逆序对的个数。

如果我们将左儿子的线段树放在前面,则产生的逆序对数为左儿子右边的sum * 右儿子左边的sum,反之同理。然后我们每次合并求出这两个之中的最小值加入ans中就好了。

代码

令我感到神奇的是,如果我们将dfs中的两句判断放在外面,常数为原来的3倍,如果不开O2就会TLE。

~~ 可我明明打的跟别人一样的代码,别人不开O2都只要300ms。自带常数型选手的悲哀。╮(╯﹏╰)╭ ~~

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cctype>
#define INF 2139062143
#define MAX 0x7ffffffffffffff
#define del(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
template<typename T>
inline void read(T&x)
{
x=0;T k=1;char c=getchar();
while(!isdigit(c)){if(c=='-')k=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=k;
}
const int maxn=8000000+5;
struct node{
int lc,rc,sum;
node(int lc=0,int rc=0,int sum=0):lc(lc),rc(rc),sum(sum){}
}T[maxn*4];
int root[maxn];
int a[maxn];
int sz;
ll ans1,ans2; void build(int x){
read(a[x]);
if(a[x]) return;
T[x].lc=++sz;build(T[x].lc);
T[x].rc=++sz;build(T[x].rc);
} void updata(int l,int r,int pos,int val,int &x){
if(!x) x=++sz;
T[x].sum+=val;
if(l==r) return;
int mid=(l+r)/2;
if(pos<=mid) updata(l,mid,pos,val,T[x].lc);
else updata(mid+1,r,pos,val,T[x].rc);
} int Merge(int x,int y){
if(!x||!y) return x+y;
ans1+=1ll*T[T[x].lc].sum*T[T[y].rc].sum;
ans2+=1ll*T[T[x].rc].sum*T[T[y].lc].sum;
T[x].lc=Merge(T[x].lc,T[y].lc);
T[x].rc=Merge(T[x].rc,T[y].rc);
T[x].sum=T[T[x].lc].sum+T[T[x].rc].sum;
return x;
} ll ans=0;
void dfs(int x){
//若为叶子结点,往下递归会TLE???
if(!a[x]){
if(T[x].lc) dfs(T[x].lc);
if(T[x].rc) dfs(T[x].rc);
ans1=0;ans2=0;
root[x]=Merge(root[T[x].lc],root[T[x].rc]);
ans+=1ll*min(ans1,ans2);
}
}
int n;
int main()
{
read(n);
build(sz=1);
for(int i=1;i<=sz;i++)
if(a[i])
updata(1,n,a[i],1,root[i]);
dfs(1);
printf("%lld\n",ans);
return 0;
}

线段树合并(【POI2011】ROT-Tree Rotations)的更多相关文章

  1. bzoj3307雨天的尾巴(权值线段树合并/DSU on tree)

    题目大意: 一颗树,想要在树链上添加同一物品,问最后每个点上哪个物品最多. 解题思路: 1.线段树合并 假如说物品数量少到可以暴力添加,且树点极少,我们怎么做. 首先在一个树节点上标记出哪些物品有多少 ...

  2. CF600E Lomsat gelral——线段树合并/dsu on tree

    题目描述 一棵树有$n$个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. 这个题意是真的窒息...具体意思是说,每个节点有一个颜色,你要找的是每个子树中颜色的众数 ...

  3. 【BZOJ2212】[Poi2011]Tree Rotations 线段树合并

    [BZOJ2212][Poi2011]Tree Rotations Description Byteasar the gardener is growing a rare tree called Ro ...

  4. 【bzoj2212】[Poi2011]Tree Rotations 权值线段树合并

    原文地址:http://www.cnblogs.com/GXZlegend/p/6826614.html 题目描述 Byteasar the gardener is growing a rare tr ...

  5. [BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】

    题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换 ...

  6. bzoj2212[Poi2011]Tree Rotations [线段树合并]

    题面 bzoj ans = 两子树ans + min(左子在前逆序对数, 右子在前逆序对数) 线段树合并 #include <cstdio> #include <cstdlib> ...

  7. 【BZOJ2212】[POI2011]Tree Rotations (线段树合并)

    题解: 傻逼题 启发式合并线段树里面查$nlog^2$ 线段树合并顺便维护一下$nlogn$ 注意是叶子为n 总结点2n 代码: #include <bits/stdc++.h> usin ...

  8. BZOJ2212 [Poi2011]Tree Rotations 线段树合并 逆序对

    原文链接http://www.cnblogs.com/zhouzhendong/p/8079786.html 题目传送门 - BZOJ2212 题意概括 给一棵n(1≤n≤200000个叶子的二叉树, ...

  9. bzoj 2212 : [Poi2011]Tree Rotations (线段树合并)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2212 思路:用线段树合并求出交换左右儿子之前之后逆序对的数量,如果数量变小则交换. 实现 ...

  10. BZOJ.2212.[POI2011]Tree Rotations(线段树合并)

    题目链接 \(Description\) 给定一棵n个叶子的二叉树,每个叶节点有权值(1<=ai<=n).可以任意的交换两棵子树.问最后顺序遍历树得到的叶子权值序列中,最少的逆序对数是多少 ...

随机推荐

  1. 使用canvas保存网页为pdf文件支持跨域

    前言 之前上一篇随笔说了Canvas截图网页为图片,下来个新需求,把网页截图后保存为PDF文件供用户下载. 前文 Canvas截图网页为图片:https://www.cnblogs.com/bubub ...

  2. [USACO17JAN]Promotion Counting

    线段树合并. 正解好像不是线段树合并,但是出于练手的目的写了线段树合并. 大概就是对于左右子树,如果有一个为空,返回非空的,如果都不为空,就把这两个整合到一起就行了. #include <ios ...

  3. Linux 查看用户命令

    1.Linux里查看所有用户 (1)在终端里.其实只需要查看 /etc/passwd文件就行了. (2)看第三个参数:500以上的,就是后面建的用户了.其它则为系统的用户. 或者用cat /etc/p ...

  4. 搞定PHP面试 - 运算符知识点整理

    一.算术运算符 1. 概览 例子 名称 结果 $a + $b 加法 $a 和 $b 的和. $a - $b 减法 $a 和 $b 的差. $a * $b 乘法 $a 和 $b 的积. $a / $b ...

  5. webKit 内核浏览器 源码分析

    如需转载,请注明出处! WebSite: http://www.jjos.org/ 作者: 姜江 linuxemacs@gmail.com QQ: 457283 这是一篇自己写于一年前的工作文档,分享 ...

  6. nginx与tomcat搭建集群,负载均衡

    --------------------------------------------------- 搭建环境(在桌面上即可完成测试) 先准备2个tomcat服务器 解压tomcat压缩包 得到 把 ...

  7. 洛谷——P1968 美元汇率

    https://www.luogu.org/problem/show?pid=1968#sub 题目背景 此处省略maxint+1个数 题目描述 在以后的若干天里戴维将学习美元与德国马克的汇率.编写程 ...

  8. 关于idea控制台乱码问题

    乱码是常有的事儿,改一下也就两分钟......不多说看图: 上图中的勾选项一定不要忘记,它可以隐藏你项目中encoding设置. 在上图两个文件中加入 -Dfile.encoding=UTF-8 在上 ...

  9. 用户体验之如何优化你的APP

    用户体验,速度为王,来几个优化APP“速度”的建议. 1.后台执行 毋庸多言,已是通常做法. 一般在执行下载任务时让其在后台运营,让用户有精力去做别的事情. 后端加载 2.提前显示 客户端与WEB的数 ...

  10. C# 中使用 Obsolete 标志 代码过期

    今天对项目做了一次更新,创建了一个新的类来替换原来的工作. 可是又不想删掉.一旦删掉在SVN上就不存在了.决定还是用 Obsolete来标志代码过期吧. MSDN上关于Obsolete 标签的介绍 h ...