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. github提交代码时遇到”Everything up-to-date“问题的解决方式

    需要创建一个新分支,将最新代码加入新分支, 再将新分支合并到主分支,然后提交主分支代码到github网站. ---------------------------------------------- ...

  2. Ajax做无刷新三级联动

    1.引入JS and Jquery包 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...

  3. C++中string的常见用法

    在ACM中主要用到string的这几个功能:赋值,添加,删除,替换,查找,比较,反向排序. 1.赋值 直接来就行: string ss; ss="aaa"; 或者 string s ...

  4. Arc083_F Collecting Balls

    传送门 题目大意 给定$N$,在$(1,0),(2,0)......(N,0)$和$(0,1),(0,2)...(0,N)$上都有$1$个机器人,同时给定$2N$个坐标$(x,y),x,y\in[1, ...

  5. BZOJ - 3123 森林 (可持久化线段树+启发式合并)

    题目链接 先把初始边建成一个森林,每棵树选一个根节点递归建可持久化线段树.当添加新边的时候,把结点数少的树暴力重构,以和它连边的那个点作为父节点继承线段树,并求出倍增数组.树的结点数可以用并查集来维护 ...

  6. Mycat 在vscode中的开发配置

    mycat是国产目前最被追捧的一款分布式数据库集群软件,有一些公司对数据库和应用都有自己的集群方案,但是更多的是一些面对庞大的数据量,而束手无策. 对于这种问题,我想百分之80遇到的是数据库的瓶颈,所 ...

  7. SQL夯实基础(五):索引的数据结构

    数据量达到十万级别以上的时候,索引的设置就显得异常重要,而如何才能更好的建立索引,需要了解索引的结构等基础知识.本文我们就来讨论索引的结构. 二叉搜索树:binary search tree 1.所有 ...

  8. Dungeon Master (BFS与DFS的应用)

    个人心得:一开始用DFS弄了半天一直输出不了结果,后面发现并没有进行判断:好不容易能够得出答案,结果超时了,才发现原来要用BFS: 对于DFS: 从一个点开始模拟能走的所有步骤,注意边界条件,走到不能 ...

  9. LeetCode Largest Palindrome Product

    原题链接在这里:https://leetcode.com/problems/largest-palindrome-product/description/ 题目: Find the largest p ...

  10. 使用.NET中的XML注释(一) -- XML注释标签讲解

    一.摘要 .Net允许开发人员在源代码中插入XML注释,这在多人协作开发的时候显得特别有用. C#解析器可以把代码文件中的这些XML标记提取出来,并作进一步的处理为外部文档. 这篇文章将展示如何使用这 ...