T1:紧急集合
涉及主要算法:LCA;
SOLUTION:
求两两之间的LCA,取MIN就是最小的qwq;
求三个结点到一个结点距离之和最小的结点以及距离和
求出两两lca,其中有两个相同,答案则为另一个,画画图就可以理解
贴一篇blog
T2:中位数:
维护两个堆,一个大根堆,一个小根堆;
对于序列:每新输入一个数,我们将之加入大根堆中,但大根堆不是无限加入的,我们设当前输入了k个数,那么大根堆中的元素至多有k/2 +1个,当大根堆中个数超过限制后,将堆顶移到小根堆,这样就可以保证大根堆堆顶永远是中位数;
next
合并果子:
这个题就很水了;
haffman tree:每次将最小的两个合并,一定是最优的;
深度越深的节点,统计的次数越多;
因此越小的应该越先被合并;
滑雪等级Ski Course Rating:
并查集问题:
- 将所有点,把边连出来
- 把所有边全删去(拿出来),按长度(高度差)从小到大排个序;
- 从小的边开始加,合并的同时统计这个集合大小,某一刻时,集合个数>=t时,最后一条边权就是难度等级D,然后ans+=D*集合个数???可能会有好多集合??
突然安利oj:
巴扎黑oj
树的同构:
一种暴力的想法:
人为定义一个根,对于每个根,算出一个Hash来,如果有两棵树的Hash集合完全相同,那么这两棵树是同构的;
如何计算树形Hash:
把所有儿子的哈希值从大到小排个序,然后按字符串的方法来,计算当前节点的hash值;
一种很巧妙的算法:
重心:找到一个点为根,最大的一棵子树节点数最少;
每一棵无根树,重心个数不会超过二;
枚举每个重心,以重心为根求出这棵有根树的最小表示,然后取字典序最大的即可。
对于有根树的最小表示,可以看成括号序列,每次把子树的括号序列按字典序排序后依次串连起来即可。
有些许懵,嗯;
有关括号序列:
POJ 2299 Ultra-QuickSort
求逆序对数;
请用树状数组做;
用树状数组维护每个数之前有多少个大于它的数;
暴力O(n^2)
0 1 2 3 4 5 6 7 8 9……
开一个数据范围大小的数组用来维护当前每个数组出现了几次,然后我们需要求一个>当前数的数的个数,可以发现这是数组后缀,然后可以转化为总数- ≤当前数的个数;
举个亚子:
假设数据范围是9,我们开一个10个的数组,分别代表0~9,假设这个序列是19260817
那么在插入0之前,序列:
0 1 2 3 4 5 6 7 8 9
0 1 1 0 0 0 0 0 0 1
此时我们插入0,我们需要寻找的是现在0之前插入的比0大的数,我们发现这是一个后缀问题,可以利用神仙操作将其转化为前缀。求出所有小于等于0的数,显然是0个,然后用当前插入的数的个数-0就是0的后缀;
然后可以用树状数组维护前缀和;
树状数组:动态将某个数+1,动态维护前缀和;
离散化:sort =>unique => 二分查找;
有关二维偏序:
xi≤xj
yi≤yj
ybt蓝书水题?!
按照y的升序(from small to big)处理;
建立一个树状数组,分别代表x为i的星星有多少个;
然后动态维护树状数组,对于每组数据,求出所有a≤当前x的数的个数(显然树状数组前缀和维护就好了);
即为答案level;
你看这个m超级小,一定有什么玄学?!
才华小哥哥上去分享,一语点不破梦中人;
开m个树状数组
每个树状数组都是0/1树状数组;
然后第i个树状数组第j个下标,表示a[j]%m==i?1:0;
下标为i的树状数组+x,把i+x%m置为1,把i%m的树状数组置为0;
思路1:把新插入的元素y插到set中,找到y的迭代器p,比较*(p++)和*(p--)与y的差值较小的就是波动√
思路2:维护一个线段树,求区间最大值和区间最小值
设每天的营业额在线段树数组中的下标为他本身的值
然后每次输入一个数时我们先在这个数的左边的区间查找最大值
再在右边的区间查找最小值
(这意味着我们要找比这个数小的最大值和比这个数大的最小值)
然后比较两者取差的绝对值最小的加到Ans里即可
看着就像线段树板子2;
单区间乘:
tag=1;开一个tag2表示加法lazy-tag
每次*c,tag*=c;sum*=c;tag*=c;
定义矩阵F=1 1 G=1
1 0 1
Σi=l~r f(ai);
Σi=l~rFai*G=(Σi=l~rFai)*G;
对于区间l~r加上一个数x,相当于变成了*Fx
对于查询l~r,就是线段树查询出这个数。
这个题需要到叶子节点才能返回;,当某个节点为0或1时就不再更新了;
同样当某个区间全部为0或1时我们就不需要在将这个区间的数递归开根了,直接返回;
开一个数组s[5]={s0,s1,s2,s3,s4},分别代表集合l中%5余0,1,2 3,4,之和;
0 1 2 6 7 8 9
s:8,10,2,6,7
Mex:最小的没有出现过的非负整数;
求出每个数组的前缀mex;
前缀mex:
19260817
00003333
拿走一个数x,在出现下一个x之前,所有前缀mex>x的都会被改变为x(区间修改去min)
然后添加一个数也随意?
枚举等差中项:
如果一个数出现过,位置为1,否则为0;每进入一个新数,把它枚举为等差数列中项,看现在以等差中项为对称轴的两侧是否对称(用hash来比较),说明这个等差中项不能产生等差数列,如果不对称,一定存在等差数列,直接输出yes;