题意:

  给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求叶子遍历序的逆序对最少。

分析:

  求逆序对我们可以想到权值线段树,所以我们对每个点建一颗线段树(为了避免空间爆炸,采取动态开点的科技)

  两个子节点可以交换,于是我们可以递归,自底向上贪心解决问题,每次线段树合并,在合并时,统计交换左右子节点后,横跨当前位置的逆序对数量,以及不交换子节点的情况下的这个数量,将更优的计入答案。这道问题就圆满解决了。

代码:

 #include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=;
struct node{ll v;int ls,rs;}t[N*];
int n,m,tot=,cnt=,nm[N],ls[N],rs[N],rt[N];
ll ans=,ans1,ans2;
void read(int x){
scanf("%d",&nm[x]);
if(!nm[x]) read(ls[x]=++cnt),
read(rs[x]=++cnt);return ;
} void update(int &x,int l,int r,int v){
if(!x) x=++tot;int mid=l+r>>;
if(l==r){t[x].v=;return ;}
if(v<=mid) update(t[x].ls,l,mid,v);
else update(t[x].rs,mid+,r,v);
t[x].v=t[t[x].rs].v+t[t[x].ls].v;
} int merge(int x,int y){
if(!x||!y) return x|y;
ans1+=(ll)t[t[x].rs].v*t[t[y].ls].v;
ans2+=(ll)t[t[x].ls].v*t[t[y].rs].v;
t[x].ls=merge(t[x].ls,t[y].ls);
t[x].rs=merge(t[x].rs,t[y].rs);
t[x].v=t[t[x].ls].v+t[t[x].rs].v;
return x;
} void dfs(int x){
if(!x) return ;
dfs(ls[x]);dfs(rs[x]);
if(!nm[x]){
ans1=ans2=;
rt[x]=merge(rt[ls[x]],rt[rs[x]]);
ans+=min(ans1,ans2);
} return ;
} int main(){
scanf("%d",&n);read();
for(int i=;i<=cnt;i++)
if(nm[i]) update(rt[i],,n,nm[i]);
dfs();printf("%lld\n",ans);
return ;
}

线段树合并

BZOJ2212【POI2011】ROT:Tree Rotation 线段树合并的更多相关文章

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

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

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

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

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

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

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

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

  5. 洛谷P3521 [POI2011]ROT-Tree Rotation [线段树合并]

    题目传送门 Tree Rotation 题目描述 Byteasar the gardener is growing a rare tree called Rotatus Informatikus. I ...

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

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

  7. [bzoj2212]Tree Rotations(线段树合并)

    解题关键:线段树合并模板题.线段树合并的题目一般都是权值线段树,因为结构相同,求逆序对时,遍历权值线段树的过程就是遍历所有mid的过程,所有能求出所有逆序对. #include<iostream ...

  8. Bzoj P2212 [Poi2011]Tree Rotations | 线段树合并

    题目链接 通过观察与思考,我们可以发现,交换一个结点的两棵子树,只对这两棵子树内的节点的逆序对个数有影响,对这两棵子树以外的节点是没有影响的.嗯,然后呢?(っ•̀ω•́)っ 然后,我们就可以对于每一个 ...

  9. bzoj2212/3702 [Poi2011]Tree Rotations 线段树合并

    Description Byteasar the gardener is growing a rare tree called Rotatus Informatikus. It has some in ...

随机推荐

  1. SQL两个字段排序

    ORDER BY  后可加2个字段,用英文逗号隔开. 1.f1用升序, f2降序,sql该这样写: 1 ORDER BY  f1, f2  DESC 2.也可以这样写,更清楚: 1 ORDER BY  ...

  2. python 高阶函数二 map()和reduce()

    一.map()函数 map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回. >>> fro ...

  3. bzoj 4405: [wc2016]挑战NPC【带花树】

    把每个筐子拆成3个,分别表示放0/1/2个,然后把这三个点两两连起来,每一个可以放在筐里的球都想这三个点连边. 这样可以发现,放0个球的时候,匹配数为1,放1个球的时候,匹配数为1,放2个球的时候,匹 ...

  4. Word Cloud (词云) - JavaScript

    在上一篇中已经分享了用 Python 创建词云了.接下来继续总结其他创建词云的方法. >> Create Word Cloud via JavaScript JavaScript 可以借助 ...

  5. (DP)51NOD 1183 编辑距离

    编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除 ...

  6. [ZJOI2011]道馆之战

    Description 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个 ...

  7. [poj3744] Scout YYF I【概率dp 数学期望】

    传送门:http://poj.org/problem?id=3744 令f(i)表示到i,安全的概率.则f(i) = f(i - 1) * p + f(i - 2) * (1 - p),若i位置有地雷 ...

  8. java数组实现红包的方法

    package Hongbao; import java.text.DecimalFormat; import java.util.Scanner; public class Hongbao { pu ...

  9. 关于表单清空的细节(reset函数或者class="reset"属性)

    在需要清空的表单的情况下, 如果是在页面中 那么就添加属性 class="reset"  也即是 <button class="reset" value= ...

  10. AJPFX对equals()方法和==异同的比较

    equals()方法是Object类的方法,所有的类都集成了此方法,还有部分类重写了这个方法,我们看一下Object类中关于该方法的的源码: public boolean equals(Object ...