用线段树记每个子树中包含的数,然后合并的时候算出来逆序对的数量(合并a,b时,就是size[ch[a][1]]*size[ch[b][0]]),来决定这个子树要不要翻转 #include<bits/stdc++.h> #define pa pair<int,int> #define CLR(a,x) memset(a,x,sizeof(a)) using namespace std; typedef long long ll; ,logn=1e7; inline ll rd(){…
3702: 二叉树 Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 600  Solved: 272[Submit][Status][Discuss] Description 现在有一棵二叉树,所有非叶子节点都有两个孩子.在每个叶子节点上有一个权值(有n个叶子节点,满足这些权值为1..n的一个排列).可以任意交换每个非叶子节点的左右孩子.要求进行一系列交换,使得最终所有叶子节点的权值按照中序遍历写出来,逆序对个数最少. Input 第一行n下面每行…
原文链接http://www.cnblogs.com/zhouzhendong/p/8079786.html 题目传送门 - BZOJ2212 题意概括 给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少. 题解 线段树合并. 博主很懒,题解不写了. 这份代码是仿照别人的写的. 代码 #include <cstring> #include <cstdio> #include <cmath> #include <al…
题目链接 BZOJ2212 题解 一棵子树内的顺序不影响其与其它子树合并时的答案,这一点与归并排序的思想非常相似 所以我们只需单独处理每个节点的两棵子树所产生的最少逆序对即可 只有两种情况,要么正序要么逆序,且这两种情况数目是互补的 如果左子树大小为\(S_l\),右子树大小为\(S_r\),那么总对数为\(S_lS_r\) 如何快速统计一棵子树中大于另一棵子树中权值的对数? 开一个权值线段树,在线段树合并过程中统计即可 由于权值是一个排列,所以复杂度是\(O(nlogn)\) 顺带一提,左右儿…
[BZOJ2212][Poi2011]Tree Rotations Description Byteasar the gardener is growing a rare tree called Rotatus Informatikus. It has some interesting features: The tree consists of straight branches, bifurcations and leaves. The trunk stemming from the gro…
显然子树内的操作不会对子树外产生影响.于是贪心,若交换之后子树内逆序对减少就交换. 这个东西可以用权值线段树计算.操作完毕后需要对两棵权值线段树合并,这个的复杂度是两棵线段树的重复节点个数.那么总复杂度不太显然的是O(nlogn).因为相当于把n个只有一个叶子的线段树合并在一起. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring&…
2212: [Poi2011]Tree Rotations Time Limit: 20 Sec Memory Limit: 259 MB Description Byteasar the gardener is growing a rare tree called Rotatus Informatikus. It has some interesting features: The tree consists of straight branches, bifurcations and lea…
原文地址:http://www.cnblogs.com/GXZlegend/p/6826614.html 题目描述 Byteasar the gardener is growing a rare tree called Rotatus Informatikus. It has some interesting features: The tree consists of straight branches, bifurcations and leaves. The trunk stemming…
题意: 给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求叶子遍历序的逆序对最少. 分析: 求逆序对我们可以想到权值线段树,所以我们对每个点建一颗线段树(为了避免空间爆炸,采取动态开点的科技) 两个子节点可以交换,于是我们可以递归,自底向上贪心解决问题,每次线段树合并,在合并时,统计交换左右子节点后,横跨当前位置的逆序对数量,以及不交换子节点的情况下的这个数量,将更优的计入答案.这道问题就圆满解决了. 代码: #include<bits/stdc++.h> #defi…
题面 bzoj ans = 两子树ans + min(左子在前逆序对数, 右子在前逆序对数) 线段树合并 #include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> #include <cstring> #define Sqr(x) ((x)*(x)) using namespace std; const int N = 2e5 + 5; const int…