题目链接:BZOJ - 2212

题目分析

子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对。

左右子树内部的逆序对与是否交换左右子树无关,是否交换左右子树取决于交换后 “跨越 x 左子树与右子树的逆序对” 是否会减小。

因此我们要求出两种情况下的逆序对数,使用线段树合并,对每个节点建一棵线段树,然后合并的同时就求出两种情况下的逆序对。

代码

  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cstdio>
  5. #include <cmath>
  6. #include <algorithm>
  7.  
  8. using namespace std;
  9.  
  10. inline void Read(int &Num)
  11. {
  12. char c = getchar();
  13. while (c < '0' || c > '9') c = getchar();
  14. Num = c - '0'; c = getchar();
  15. while (c >= '0' && c <= '9')
  16. {
  17. Num = Num * 10 + c - '0';
  18. c = getchar();
  19. }
  20. }
  21.  
  22. typedef long long LL;
  23.  
  24. inline LL gmin(LL a, LL b) {return a < b ? a : b;}
  25.  
  26. const int MaxN = 400000 + 5, MaxNode = 4000000 + 5;
  27.  
  28. int n, IndexT, Index, RT;
  29. int A[MaxN], Tree[MaxN][2], Root[MaxN], T[MaxNode], Son[MaxNode][2];
  30.  
  31. LL Ans0, Ans1, Ans;
  32.  
  33. void Read_Tree(int &x)
  34. {
  35. x = ++IndexT;
  36. Read(A[x]);
  37. if (A[x] != 0) return;
  38. Read_Tree(Tree[x][0]);
  39. Read_Tree(Tree[x][1]);
  40. }
  41.  
  42. inline void Update(int x)
  43. {
  44. T[x] = T[Son[x][0]] + T[Son[x][1]];
  45. }
  46.  
  47. void Insert(int &x, int s, int t, int Pos)
  48. {
  49. if (x == 0) x = ++Index;
  50. if (s == t)
  51. {
  52. T[x] = 1;
  53. return;
  54. }
  55. int m = (s + t) >> 1;
  56. if (Pos <= m) Insert(Son[x][0], s, m, Pos);
  57. else Insert(Son[x][1], m + 1, t, Pos);
  58. Update(x);
  59. }
  60.  
  61. int Merge(int x, int y)
  62. {
  63. if (!x) return y;
  64. if (!y) return x;
  65. Ans0 += (LL)T[Son[x][1]] * (LL)T[Son[y][0]];
  66. Ans1 += (LL)T[Son[x][0]] * (LL)T[Son[y][1]];
  67. Son[x][0] = Merge(Son[x][0], Son[y][0]);
  68. Son[x][1] = Merge(Son[x][1], Son[y][1]);
  69. Update(x);
  70. return x;
  71. }
  72.  
  73. void Solve(int x)
  74. {
  75. if (A[x]) return;
  76. Solve(Tree[x][0]); Solve(Tree[x][1]);
  77. Ans0 = Ans1 = 0;
  78. Root[x] = Merge(Root[Tree[x][0]], Root[Tree[x][1]]);
  79. Ans += gmin(Ans0, Ans1);
  80. }
  81.  
  82. int main()
  83. {
  84. scanf("%d", &n);
  85. Read_Tree(RT);
  86. for (int i = 1; i <= IndexT; ++i)
  87. if (A[i] != 0) Insert(Root[i], 1, n, A[i]);
  88. Solve(RT);
  89. cout << Ans << endl;
  90. return 0;
  91. }

  

[BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. bzoj 2212 : [Poi2011]Tree Rotations (线段树合并)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2212 思路:用线段树合并求出交换左右儿子之前之后逆序对的数量,如果数量变小则交换. 实现 ...

随机推荐

  1. javascript优化工具 Doloto

    Doloto是“Download Time Optimizer”的简写.官方页面上说它对于大型复杂的AJAX应用尤其的有用,因为这些应用包含了大量的 JavaScript 代码.简单的说,它的工作原理 ...

  2. 基于 JQUERY 网页 banner

    demo.html <html> <head> <title>demo</title> <link href="css/PaPaBann ...

  3. JavaScript高级程序设计(第三版)学习笔记6、7章

    第6章,面向对象的程序设计 对象: 1.数据属性 configurable,表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或能否把属性修改为访问器属性,默认为true ‚en ...

  4. 百度贴吧图片抓取工具(Python)

    废话不多说,直接上源码. import os,urllib,urllib2,re path='E:/img' #图片保存路径 url=raw_input('Please input URL:')#贴吧 ...

  5. hibernate设置mysql的timestamp默认值技巧

    首先,要想使用数据库中配置的默认值就必须不让hibernate覆盖了默认值,需要配置property insert="false" update="false" ...

  6. ### 学习《C++ Primer》- 8

    Part 8: 面向对象(第15章) // @author: gr // @date: 2015-01-09 // @email: forgerui@gmail.com 一.OOP 面向对象程序设计的 ...

  7. mysql net连接读取结果为乱码 Incorrect string value

    在mysql直接查询中文正常,通过连接到mysql读取中文内容为乱码.同时插入中文内容也失败提示 Incorrect string value: '\xBC\xA4\xB7\xA2\xBF\xB4.. ...

  8. 学习块格式化上下文(BlockFormattingContext)

    什么是BFC BFC全称是Block Formatting Context,即块格式化上下文.它是CSS2.1规范定义的,关于CSS渲染定位的一个概念.要明白BFC到底是什么,首先来看看什么是视觉格式 ...

  9. 16_会话技术_Session案例

    [购物车中的信息保存] [Book.java] package com.Higgin.shopping; public class Book { private String id; private ...

  10. Update msi using vbscript

    参考: http://stackoverflow.com/questions/1609250/how-do-i-add-update-a-property-inside-an-msi-from-the ...