bzoj 2733 平衡树启发式合并】的更多相关文章

首先对于一个连通块中,询问我们可以直接用平衡树来求出排名,那么我们可以用并查集来维护各个块中的连通情况,对于合并两个平衡树,我们可以暴力的将size小的平衡树中的所有节点删掉,然后加入大的平衡树中,因为每个点只可能被删除插入logn次,所以时间复杂度为nlog^2n. /**************************************************************     Problem: 2733     User: BLADEVIL     Language:…
题意:给定一个带点权的无向图,有两种操作: 1.将两个连通分量合并. 2.查询某个连通分量里的第K大点. 题解: 用并查集维护连通关系,一开始建立n棵splay树,然后不断合并,查询. 处理技巧: 1.每个顶点u所在的Splay就是T[find(u)]. 2.每个顶点在树中对应的节点编号就是该顶点的编号. #include <cstdio> #include <iostream> #define maxn 100110 using namespace std; ], siz[max…
枚举树上的每个结点做管理者, 贪心地取其子树中薪水较低的, 算出这个结点为管理者的满意度, 更新答案. 用平衡树+启发式合并, 时间复杂度为O(N log²N) --------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostrea…
题目类型:平衡树启发式合并 传送门:>Here< 题意:节点可以连边(不能断边),询问任意两个节点的连通性与一个连通块中排名第\(k\)的节点 解题思路 如果不需要询问排名,那么并查集即可.如果只询问排名第一,那么左偏树即可.现在要询问排名第\(k\)小,就需要用平衡树来解决 平衡树求解排名第\(k\)是轻而易举的,然而怎么合并两棵平衡树呢? 启发式合并.所谓启发式合并,就是暴力合并-- 所谓启发式合并(不仅仅是平衡树),就是比较要合并的两个结构,选择较小的那一个结构,将其中节点一个一个拆下来…
首先我们对于一颗树,要选取最多的节点使得代价和不超过m,那么我们可以对于每一个节点维护一个平衡树,平衡树维护代价以及代价的和,那么我们可以在logn的时间内求出这个子树最多选取的节点数,然后对于一个节点的平衡树我们可以由他的子节点启发式合并而来,时间复杂度nlog^2n. 这道题还可以用左偏树来解决,左偏树为一种可合并堆,合并,删除,插入都在logn内完成,那么这道题的时间复杂度还可以nlogn. 反思:我写的是左偏树的,手残把value打成cost了= =,查了半天. /***********…
题意: 带权联通块,添边与查询联通块中第k大. SOL: splay合并+并查集. 我以为splay可以用奇技淫巧来简单合并...调了一下午终于幡然醒悟...于是就只好一个一个慢慢插...什么启发式合并...说的那么高级其实那么丝帛. 实现得非常渣...中序遍历3060ms,换成队列并没有快起来...难道是我的splay本身就不对?... %%%hzw的线段树...发现其实线段树合并更简单更快...被splay蒙蔽了眼睛...思路不够开阔...唉... Code: /*=============…
用并查集维护联通性.对每个联通块维护一个平衡树.合并时启发式合并.比较懒,用了pb_ds. #include<cstdio> #include<ext/pb_ds/assoc_container.hpp> #include<ext/pb_ds/tree_policy.hpp> using namespace std; using namespace __gnu_cxx; using namespace __gnu_pbds; tree<]; tree<int…
题目: BZOJ1483 分析: (这题码了一下午,码了近250行,但是意外跑的比本校各位神仙稍快,特写博客纪念) 首先能看出一个显然的结论:颜色段数只会变少不会变多. 我们考虑用并查集维护区间,对于每个区间维护它的起点和终点.建\(n\)棵平衡树,第\(i\)棵存颜色为\(i\)的区间.把\(x\)变成\(y\)时进行启发式合并,同时对于\(x\)上的每个结点\([a,b]\),在\(y\)中找\(a-1\)和\(b+1\)所在区间.如果存在则合并,并答案减\(1\):若不存在则向\(y\)中…
思路:将颜色相同的建成一个链表, 变颜色的时候进行链表的启发式合并.. 因为需要将小的接到大的上边,所以要用个f数组. #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> using namespace std; ; ; const int inf = 0x3f3f3f3f; co…
首先我们可以比较容易的在n的时间内算出来开始的答案,我们维护一些链表,分别表示不同的颜色,那么我们在计算答案的时候,只需要扫一遍所有的链表,判断链表相邻两项是否在序列中相邻,不相邻的话肯定在这其中的一个唯一有一个断的点,也就是分成了两个不同的颜色段,直接累加答案就好了. 然后我们对于每个询问,将颜色x换成颜色y,那么我们找到这两种颜色的链表,将小的链表连接到大的链表之后,同时统计由于合并两个链表而对答案造成的影响.这样直接合并是不行的,因为我们由于链表的长度而改变了合并的顺序,所以我们可以记录一…