P3521 [POI2011]ROT-Tree Rotations】的更多相关文章

P3521 [POI2011]ROT-Tree Rotations 题意: 给你一颗树,只有叶子节点有权值,你可以交换一个点的左右子树,问你最小的逆序对数 题解: 线段树维护权值个个数即可 然后左右子树合并时计算交换和不交换的贡献取一个min即可 代码: /** * ┏┓ ┏┓ * ┏┛┗━━━━━━━┛┗━━━┓ * ┃ ┃ * ┃ ━ ┃ * ┃ > < ┃ * ┃ ┃ * ┃... ⌒ ... ┃ * ┃ ┃ * ┗━┓ ┏━┛ * ┃ ┃ Code is far away from b…
2212: [Poi2011]Tree Rotations Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 391  Solved: 127[Submit][Status] Description Byteasar the gardener is growing a rare tree called Rotatus Informatikus. It has some interesting features: The tree consists o…
线段树的合并..对于一个点x, 我们只需考虑是否需要交换左右儿子, 递归处理左右儿子. #include<bits/stdc++.h> using namespace std; #define M(l, r) (((l) + (r)) >> 1) typedef long long ll; ; ; struct Node *null, *pt; struct Node { Node *l, *r; int cnt; Node() : cnt() { l = r = null; }…
P3521 [POI2011]ROT-Tree Rotations loj2163 [POI2011]ROT-Tree Rotations(数据加强) (loj的数据套了个fread优化才过...) 显然地,对于一棵线段树(树根设为$rt$),是否翻转它的子树的子树,对于跨$mid$的逆序对数量没有影响. 那么我们可以层层统计(设左右子树为$lc,rc$): 不翻转时,该层(跨$mid$)的逆序对:$a[a[a[rt].lc].rc].sum*a[a[a[rt].rc].lc].sum$ 翻转时…
2212: [Poi2011]Tree Rotations https://www.lydsy.com/JudgeOnline/problem.php?id=2212 分析: 线段树合并. 首先对每个节点建立一棵权值线段树,然后遍历整棵树,从叶子节点开始合并,每次合并两个节点的主席树,判断是否交换这两个节点,求出这两个节点分在前面所形成的逆序对. 求逆序对:对于主席树中的右子树一定比左子树大,所以每次合并一个节点时,直接用右子树的个数乘以左子树的个数,不断递归. 代码: #include<cst…
P3521 [POI2011]ROT-Tree Rotations 题意:递归给出给一棵\(n(1≤n≤200000)\)个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少. 大体给出方式: 第一行一个正整数\(n\),表示该二叉树的叶节点的个数: 下面若干行,每行一个数\(p\): 如果\(p=0\),表示这个节点不是叶节点,递归地向下读入其左孩子和右孩子的信息: 如果\(p \neq 0\) ,表示这个节点是叶节点,权值为\(p\) . 本来想学一下启发式合并的,结果被一…
[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…
POI2011 Tree Rotations 给定一个n<=2e5个叶子的二叉树,可以交换每个点的左右子树.要求前序遍历叶子的逆序对最少. 由于对于当前结点x,交换左右子树,对于范围之外的逆序对个数并没有影响,所以可以进行线段树合并,合并时统计l在左边还是在右边更优. #include <cstdio> #include <cctype> using namespace std; typedef long long LL; inline void read(int &…
二叉树 Tree Rotations bzoj-3702 bzoj-2212 Poi-2011 题目大意:现在有一棵二叉树,所有非叶子节点都有两个孩子.在每个叶子节点上有一个权值(有n个叶子节点,满足这些权值为1到n的一个排列).可以任意交换每个非叶子节点的左右孩子.要求进行一系列交换,使得最终所有叶子节点的权值按照中序遍历写出来,逆序对个数最少. 注释:$2\le n \le 2\cdot 10^5$. 想法:显然,对于一个节点的两个儿子lson和rson,无论lson和rson内部如何操作,…
bzoj 2212 Tree Rotations 考虑一个子树 \(x\) 的左右儿子分别为 \(ls,rs\) .那么子树 \(x\) 内的逆序对数就是 \(ls\) 内的逆序对数,\(rs\) 内的逆序对数,跨越 \(ls,rs\) 的逆序对数三者之和. 交换 \(ls,rs\) 显然对前两种的答案没有影响,只需最大化最后一种答案. 对每个叶子节点开一棵权值线段树向上合并,选取权值中点 \(mid\) 划分开,那么两种情况在当前层产生的贡献即为 \(ls\) 的左子树大小 \(\times\…
线段树合并([POI2011]ROT-Tree Rotations) 题意 现在有一棵二叉树,所有非叶子节点都有两个孩子.在每个叶子节点上有一个权值(有nn个叶子节点,满足这些权值为1-n1-n的一个排列).可以任意交换每个非叶子节点的左右孩子. 要求进行一系列交换,使得最终所有叶子节点的权值按照前序遍历序写出来,逆序对个数最少. 解法 我们对每一个叶子节点建立一颗权值线段树,然后,我们考虑将两个叶子节点上的线段树合并起来,然后我们考虑逆序对的个数. 如果我们将左儿子的线段树放在前面,则产生的逆…
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 ground is also a branch. Each branch…
原文地址: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…
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 ground is also a branch. Each branch…
题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换左右子树无关,是否交换左右子树取决于交换后 “跨越 x 左子树与右子树的逆序对” 是否会减小. 因此我们要求出两种情况下的逆序对数,使用线段树合并,对每个节点建一棵线段树,然后合并的同时就求出两种情况下的逆序对. 代码 #include <iostream> #include <cstdli…
题目分析: 写的无旋treap应该跑不过,但bzoj判断的总时限.把相关实现改成线段树合并就可以了. 代码: #include<bits/stdc++.h> using namespace std; ; int n; ],num,val[maxn]; ][],sz[maxn],rot[maxn],data[maxn],key[maxn]; ; int merge(int r1,int r2){ ) ) return r1; if(key[r1] < key[r2]){ son[r1][]…
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2212 [题目大意] 给出一棵二叉树,每个叶节点上有一个权值,现在可以任意交换左右儿子, 使得逆序对最少,求最少的逆序对数量 [题解] 我们发现对于每个非叶节点来说,其贡献值为左右两个儿子的权值树上, 每个节点想反位置的数量和乘积,比如左儿子的权值树左节点和右儿子权值树的右节点相乘, 那么我们对于每个节点建立一颗权值线段树,仅保留非0链, 递归合并这些权值线段树,同时每次将相反位置数量…
一句话题意(不用我改了.....):给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少. ......这题输入很神烦呐... 给你一棵二叉树的dfs序(考场上没发现2333),只有叶子结点有值,然后求逆序对大小 在考场上,建树建了好久,然后暴力暴了好久,然后得到了0分的好成绩呢(我真棒) 正解其实也不难想(但是当时不会权值线段树) 题解: 其实很简单,想想:对于一层的逆序对,数量是一定的.也就是说,无论怎么转当前子树,对上一层的逆序对数量是没有影…
题意 给一棵\(n(1 \le n \le 200000)\)个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少. 分析 可以发现如果交换非叶结点的左右子树,对子树内的交换无影响,对子树外的交换也无影响,所以答案的贡献只是左子树与右子树之间是否交换得到的最小的逆序对数. 题解 考虑分治,对于一个点\(x\),我们只需要将其其中的一个子树的叶子插入到bit中,然后用另一个子树的叶子就能求得其逆序对数.那么发现一个点在遍历过程中可能插入的次数不只1次,对复杂度的影响主要就是重复插…
题目链接 [BZOJ] [洛谷] [LOJ] 题解 由于是前序遍历,那么讨论一棵树上的逆序对的情况. 两个节点都在左子树上 两个节点都在右子树上 两个节点分别在不同的子树上. 前两种情况其实也可以归结于第三种情况. 原因 因为两个节点不可能占据一个位置. 根据容斥原理,为了保证答案的正确性,我们递归求解不能计算两遍相同的答案. 回到正题 所以我们只需要讨论跨越两个子树的情况. 很显然,左子树中的所有点的\(dfs\)序都比右子树的子树中的小. 那么如果要交换,就是相反一下. 比较容易可以想到对于…
题面 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…
题目链接 \(Click\) \(Here\) 线段树合并,没想到学起来意外的很简单,一般合并权值线段树. 建树方法和主席树一致,即动态开点.合并方法类似于\(FHQ\)的合并,就是把两棵树的信息整合到一个里面.暂时没写过定义域不同的线段树合并,具体方法也想象不出来,写到了再详细讲吧. 算法复杂度:均摊\(O(NlogN)\),实际空间时间复杂度都不够稳定,需要谨慎使用. #include <bits/stdc++.h> using namespace std; const int N = 2…
题解: 傻逼题 启发式合并线段树里面查$nlog^2$ 线段树合并顺便维护一下$nlogn$ 注意是叶子为n 总结点2n 代码: #include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for(int i=h;i<=t;i++) #define dep(i,t,h) for(int i=t;i>=h;i--) #defin…
原文链接http://www.cnblogs.com/zhouzhendong/p/8079786.html 题目传送门 - BZOJ2212 题意概括 给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少. 题解 线段树合并. 博主很懒,题解不写了. 这份代码是仿照别人的写的. 代码 #include <cstring> #include <cstdio> #include <cmath> #include <al…
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2212 思路:用线段树合并求出交换左右儿子之前之后逆序对的数量,如果数量变小则交换. 实现代码: #include<bits/stdc++.h> using namespace std; #define ll long long ; int n,cnt,idx; ll ans,cnt1,cnt2; int v[M],l[M],r[M],root[M]; ],ls[M*],rs[M*];…
思路 发现每个子树内的交换情况不会对子树外造成影响,所以可以利用贪心的思想,线段树合并找出当前子树的合并的最小值直接累加给答案即可 我脑补的线段树合并貌似不太优秀的样子...每次都要新建节点,学习了直接把y合并到x上的想法,但是因为#define int long long的坏习惯导致MLE,最后还是要写内存池... 代码 #include <cstdio> #include <algorithm> #include <cstring> #include <que…
题目链接 \(Description\) 给定一棵n个叶子的二叉树,每个叶节点有权值(1<=ai<=n).可以任意的交换两棵子树.问最后顺序遍历树得到的叶子权值序列中,最少的逆序对数是多少. \(Solution\) 很重要的一点是在子树内部交换左右儿子对其它子树是没有影响的.(当然更大区间内交换两棵子树对子树内部也是没有影响的) 所以DFS,对每个节点的两棵子树,如果换了更优就换,不优就不换. 怎么统计两棵子树换/不换产生的逆序对数呢,用两棵子树的值域线段树合并解决.换/不换产生的逆序对数根…
题目链接 BZOJ2212 题解 一棵子树内的顺序不影响其与其它子树合并时的答案,这一点与归并排序的思想非常相似 所以我们只需单独处理每个节点的两棵子树所产生的最少逆序对即可 只有两种情况,要么正序要么逆序,且这两种情况数目是互补的 如果左子树大小为\(S_l\),右子树大小为\(S_r\),那么总对数为\(S_lS_r\) 如何快速统计一棵子树中大于另一棵子树中权值的对数? 开一个权值线段树,在线段树合并过程中统计即可 由于权值是一个排列,所以复杂度是\(O(nlogn)\) 顺带一提,左右儿…
题目大意:给一棵$n(n\leqslant2\times10^5)$个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少.输出最少的逆序对个数 题解:线段树合并,对于每个节点求出交换左右子树和不交换的答案. 卡点:没开$long\;long$ C++ Code: #include <cstdio> #define maxn 200010 #define N maxn * 20 inline long long min(long long a, long long b) {re…
题意: 给一棵n(1≤n≤200000个叶子的二叉树,可以交换每个点的左右子树,要求叶子遍历序的逆序对最少. 分析: 求逆序对我们可以想到权值线段树,所以我们对每个点建一颗线段树(为了避免空间爆炸,采取动态开点的科技) 两个子节点可以交换,于是我们可以递归,自底向上贪心解决问题,每次线段树合并,在合并时,统计交换左右子节点后,横跨当前位置的逆序对数量,以及不交换子节点的情况下的这个数量,将更优的计入答案.这道问题就圆满解决了. 代码: #include<bits/stdc++.h> #defi…