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. New Concept English three (47)

    Pollution is the price we pay for an overpopulated, over industrialized planet. When you come to thi ...

  2. const指针和指向const的指针

    int *const p=&a; 这是const指针,这种指针必须在定义时就给出它所指向的地址,否则会error:uninitialized const 'p'.const指针的指针本身是co ...

  3. 关于stl advance函数移动步数超过容器大小(越界)的研究

    今天使用advance遇到个问题,当advance移动步数超过容器大小时,表现的结果居然不一样. 再来看下stl源码 template<typename _BidirectionalIterat ...

  4. python whl包的安装

    1.首先安装PIP. https://pip.pypa.io/en/latest/installing.html#install-pip python get-pip.py 2.设置好环境变量: C: ...

  5. mac下安装libpng环境

    用go写一个爬虫工具时需要使用一个go的库,而这个库有需要使用libpng库,不然编译就会提示说 png.h找不到等之类的信息,于是想到应该和windows一样需要安装gcc环境,然后让gcc里安装l ...

  6. HihoCoder1080 更为复杂的买卖房屋姿势(线段树+多重lazy)

    描述 小Hi和小Ho都是游戏迷,“模拟都市”是他们非常喜欢的一个游戏,在这个游戏里面他们可以化身上帝模式,买卖房产. 在这个游戏里,会不断的发生如下两种事件:一种是房屋自发的涨价或者降价,而另一种是政 ...

  7. Python+Apache+CGI完全配置

    http://www.tuicool.com/articles/jIZfaqQ 操作系统环境:Ubuntu 15.10 0.需求原因 想在我的Linux上架设Apache来运行CGI程序,方便以后用A ...

  8. 20181229模拟 T1 palindrome

    20181229模拟 T1 palindrome 题意 : \(S\)是字符串\(s\)的子串可重集,求\(\sum\limits_{x\in S}\sum\limits_{y\in S}(|x|+| ...

  9. Node中没搞明白require和import,你会被坑的很惨

    ES6标准发布后,module成为标准,标准的使用是以export指令导出接口,以import引入模块,但是在我们一贯的node模块中,我们采用的是CommonJS规范,使用require引入模块,使 ...

  10. Day2-VIM(一):移动

    基础 字符移动 k 上移 k h 左移 h l l 右移 j j 下移 你也可以使用键盘上的方向键来移动,但这么做h j k l的存在就失去了意义 之所以使用h j k l来控制方向,其主要目的是让你 ...