BZOJ 2212

从下到上线段树合并。

考虑到每一个子树内部产生的贡献不可能通过换儿子消除,所以一次更换只要看看把哪个儿子放在左边产生的逆序对数少就可以了。

逆序对数可以在线段树合并的时候顺便算出来。

由于只有叶子结点有权值 + 二叉树的特性,大大方便了这道题的代码和细节处理。

注意点数总共要开到$2 * n$。

时间复杂度$O(nlogn)$。

Code:

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll; const int N = 4e5 + ; int m, n = , rt = ;
ll ans = 0LL; struct Node {
int lc, rc, w;
} a[N]; inline void read(int &X) {
X = ; char ch = ; int op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline ll min(ll x, ll y) {
return x > y ? y : x;
} void build(int &now) {
now = ++n;
read(a[now].w);
if(a[now].w) return;
build(a[now].lc), build(a[now].rc);
} namespace SegT {
struct Node {
int lc, rc;
ll siz;
} s[N * ]; int sta[N * ], top = , root[N], nodeCnt = ;
ll res1, res2; inline void push(int now) {
sta[++top] = now;
} inline int newNode() {
if(top) return sta[top--];
else return ++nodeCnt;
} #define lc(p) s[p].lc
#define rc(p) s[p].rc
#define siz(p) s[p].siz
#define mid ((l + r) >> 1) inline void up(int p) {
if(!p) return;
siz(p) = siz(lc(p)) + siz(rc(p));
} void ins(int &p, int l, int r, int x) {
if(!p) p = newNode();
++siz(p);
if(l == r) return; if(x <= mid) ins(lc(p), l, mid, x);
else ins(rc(p), mid + , r, x);
} int merge(int u, int v, int l, int r) {
if(!u || !v) return u + v; res1 += siz(rc(u)) * siz(lc(v));
res2 += siz(rc(v)) * siz(lc(u)); int p = newNode();
if(l == r) siz(p) = siz(u) + siz(v);
else {
lc(p) = merge(lc(u), lc(v), l, mid);
rc(p) = merge(rc(u), rc(v), mid + , r);
up(p);
}
push(u), push(v);
return p;
} void print(int p, int l, int r) {
if(l == r) {
printf("%lld", siz(p));
return;
} print(lc(p), l, mid), print(rc(p), mid + , r);
} inline void deb(int x) {
print(root[x], , m);
} #undef lc
#undef rc
#undef mid
#undef siz } using namespace SegT; void solve(int now) {
if(a[now].w) return;
solve(a[now].lc), solve(a[now].rc); res1 = res2 = 0LL;
root[now] = merge(root[a[now].lc], root[a[now].rc], , m);
ans += min(res1, res2);
} int main() {
read(m);
build(rt); /* for(int i = 1; i <= n; i++)
printf("%d %d %d\n", a[i].lc, a[i].rc, a[i].w);
printf("\n"); */ for(int i = ; i <= n; i++)
if(a[i].w) ins(root[i], , m, a[i].w); /* for(int i = 1; i <= n; i++) {
if(!a[i].w) continue;
deb(i);
printf("\n");
} */ solve(rt); printf("%lld\n", ans);
return ;
}

Luogu 3521 [POI2011]ROT-Tree Rotations的更多相关文章

  1. BZOJ2212: [Poi2011]Tree Rotations

    2212: [Poi2011]Tree Rotations Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 391  Solved: 127[Submi ...

  2. BZOJ 2212: [Poi2011]Tree Rotations( 线段树 )

    线段树的合并..对于一个点x, 我们只需考虑是否需要交换左右儿子, 递归处理左右儿子. #include<bits/stdc++.h> using namespace std; #defi ...

  3. 2212: [Poi2011]Tree Rotations

    2212: [Poi2011]Tree Rotations https://www.lydsy.com/JudgeOnline/problem.php?id=2212 分析: 线段树合并. 首先对每个 ...

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

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

  5. POI2011 Tree Rotations

    POI2011 Tree Rotations 给定一个n<=2e5个叶子的二叉树,可以交换每个点的左右子树.要求前序遍历叶子的逆序对最少. 由于对于当前结点x,交换左右子树,对于范围之外的逆序对 ...

  6. [bzoj3702/2212][Poi2011]二叉树/Tree Rotations_线段树

    二叉树 Tree Rotations bzoj-3702 bzoj-2212 Poi-2011 题目大意:现在有一棵二叉树,所有非叶子节点都有两个孩子.在每个叶子节点上有一个权值(有n个叶子节点,满足 ...

  7. bzoj 2212 Tree Rotations

    bzoj 2212 Tree Rotations 考虑一个子树 \(x\) 的左右儿子分别为 \(ls,rs\) .那么子树 \(x\) 内的逆序对数就是 \(ls\) 内的逆序对数,\(rs\) 内 ...

  8. Luogu 3690 Link Cut Tree

    Luogu 3690 Link Cut Tree \(LCT\) 模板题.可以参考讲解和这份码风(个人认为)良好的代码. 注意用 \(set\) 来维护实际图中两点是否有直接连边,否则无脑 \(Lin ...

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

    线段树合并([POI2011]ROT-Tree Rotations) 题意 现在有一棵二叉树,所有非叶子节点都有两个孩子.在每个叶子节点上有一个权值(有nn个叶子节点,满足这些权值为1-n1-n的一个 ...

随机推荐

  1. 如何选择MySQL数据库的安装方式

     MySQL数据库安装有yum安装,rpm安装,二进制编译安装,cmake,或者make安装,但是选择什么样的安装方式则全看实际应用场景. 下为网友总结安装方式选择:   若是对数据库要求不太高的场景 ...

  2. C程序设计语言阅读笔记

    预处理器 ->.i  编译器 >.s 汇编器 >.o 链接器  --可执行文件   ------------------ math.h头文件包含各种数学函数的声明,所有函数都返回一个 ...

  3. ERR_PTR PTR_ERR IS_ERR ERROR

    在linux-x.xx/include/uapi/asm-generic/errno-base.h和errno.h里分别定义了返回错误的信息. errno-base.h: #ifndef _ASM_G ...

  4. 利用GPU实现翻页效果(分享自知乎网)

    https://zhuanlan.zhihu.com/p/28836892?utm_source=qq&utm_medium=social 首发于Runtime 写文章 利用GPU实现翻页效果 ...

  5. qq群文件管理

    一.怎样登录QQ群空间查看.管理群文件 1)登录自己的QQ,打开主面板!小编在这里以访问自己的群“我们的六班”为例.2)鼠标移动到主面板中“我们的六班”群图标处,右建单击——选择“访问QQ群空间”—— ...

  6. Java代码使用正则验证和常用工具方法

    1.正则验证邮箱 public static boolean checkEmail(String email){ boolean flag = false; try{ String check = & ...

  7. DOM对象和JQuery对象互转

    实现点击某一个单元格,将单元格内部的sql提交执行: <td onclick="submitSqlExecute(this)">...<span>${ctx ...

  8. Python time和datatime模块

    time和datatime模块 时间相关的操作,时间有三种表示方式: 时间戳               1970年1月1日之后的秒,即:time.time() 格式化的字符串    2014-11- ...

  9. webrtc自带client的视频引擎创建代码走读

    src\webrtc\examples\peerconnection\client\conductor.ccbool Conductor::InitializePeerConnection()1 we ...

  10. HDFS之三:hdfs参数配置详解

    1.hdfs-site.xml 参数配置 – dfs.name.dir – NameNode 元数据存放位置 – 默认值:使用core-site.xml中的hadoop.tmp.dir/dfs/nam ...