显然子树内的操作不会对子树外产生影响。于是贪心,若交换之后子树内逆序对减少就交换。

  这个东西可以用权值线段树计算。操作完毕后需要对两棵权值线段树合并,这个的复杂度是两棵线段树的重复节点个数。那么总复杂度不太显然的是O(nlogn)。因为相当于把n个只有一个叶子的线段树合并在一起。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 400010
int n,cnt=,tot=,root[N];
long long ans=,ansl,ansr;
struct data{int l,r,x;}tree[N<<];
void add(int &k,int l,int r,int x)
{
if (!k) k=++cnt;
tree[k].x++;
if (l==r) return;
int mid=l+r>>;
if (x<=mid) add(tree[k].l,l,mid,x);
else add(tree[k].r,mid+,r,x);
}
int merge(int x,int y,int l,int r)
{
if (!x||!y) return x|y;
ansl+=1ll*tree[tree[x].l].x*tree[tree[y].r].x;
ansr+=1ll*tree[tree[x].r].x*tree[tree[y].l].x;
tree[x].x+=tree[y].x;
int mid=l+r>>;
tree[x].l=merge(tree[x].l,tree[y].l,l,mid),
tree[x].r=merge(tree[x].r,tree[y].r,mid+,r);
return x;
}
int get()
{
int x=read(),t=++tot;
if (x) add(root[t],,n,x);
else
{
int l=get(),r=get();
ansl=,ansr=;
root[t]=merge(root[l],root[r],,n);
ans+=min(ansl,ansr);
}
return t;
}
int main()
{
freopen("bzoj2212.in","r",stdin);
freopen("bzoj2212.out","w",stdout);
n=read();
get();
cout<<ans;
fclose(stdin);fclose(stdout);
return ;
}

BZOJ2212 POI2011Tree Rotations(线段树合并)的更多相关文章

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

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

  2. bzoj2212 Tree Rotations 线段树合并+动态开点

    题目传送门 思路: 区间合并线段树的题,第一次写,对于一颗子树,无论这个子树怎么交换,都不会对其他子树的逆序对造成影响,所以就直接算逆序对就好. 注意叶子节点是1到n的全排列,所以每个权值都只会出现1 ...

  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/zhouzhendong/p/8079786.html 题目传送门 - BZOJ2212 题意概括 给一棵n(1≤n≤200000个叶子的二叉树, ...

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

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

  6. [POI2011]ROT-Tree Rotations 线段树合并|主席树 / 逆序对

    题目[POI2011]ROT-Tree Rotations [Description] 现在有一棵二叉树,所有非叶子节点都有两个孩子.在每个叶子节点上有一个权值(有\(n\)个叶子节点,满足这些权值为 ...

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

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

  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. 7-51单片机ESP8266学习-AT指令(8266TCP服务器,编写自己的C#TCP客户端发信息给单片机控制小灯的亮灭)

    http://www.cnblogs.com/yangfengwu/p/8780182.html 自己都是现做现写,如果想知道最终实现的功能,请看最后 先把源码和资料链接放到这里 链接: https: ...

  2. 画线函数Glib_Line算法的研究

      在这里首先先简单把我对函数的功能的理解阐述一下,方便后面的分析:Glib_Line函数实现的功能是通过参数给定(x1,y1,x2,y2,color),来确定起点(x1,y1)和终点(x2,y2)两 ...

  3. c语言程序设计 第一例子

    #include <studio.h> int main(){ printf("this is  dog.\n"); return 0; } studio.h 表示st ...

  4. 递归遍历对象获取value值

    let menu = { name: '一级菜单', data: { name: '二级菜单', data: { name: '三级菜单', data: { name: '四级菜单' } } } }; ...

  5. CSS 列表实例

    CSS 列表属性允许你放置.改变列表项标志,或者将图像作为列表项标志.CSS 列表属性(list)属性 描述list-style 简写属性.用于把所有用于列表的属性设置于一个声明中.list-styl ...

  6. os模块 与 sys模块

    os模块 os模块是与操作系统交互的一个接口 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前脚本工 ...

  7. wordcount程序中的应用与拓展

    设计思路: 关键是思路,首先知道 单词, 行,字符, 他们有什么特点: 1.单词,标准的是遇到空格后,单词数,自动加一. 2.行是以\n结束的, 也就是说, 遇到\n行数加一,当然也视你的操作系统而言 ...

  8. 《Linux内核设计与实现》第17章学习笔记

    第17章.设备与模块 17.1设备类型 1.块设备(blkdev): 寻址以块为单位,通常支持重定位操作.通过称为“块设备节点”的特殊文件来访问. 2.字符设备(cdev): 不可寻址,仅提供数据的流 ...

  9. Linux 第七周实验 及总结

    姬梦馨 原创作品 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 第七周 Linux内核如何装载和启动一 ...

  10. Linux内核分析 读书笔记 (第十八章)

    第十八章 调试 18.1 准备开始 1. 需要的只是: 一个bug 一个藏匿bug的内核版本 相关内核代码的知识和运气 2. 在跟踪bug的时候,掌握的信息越多越好. 18.2 内核中的bug 1.  ...