【技巧总结】——数据结构

树状数组

特别注意,树状数组下标为0是不可用的,若调用,记得加上偏移量!

求逆序对

用树状数组来记录 a [ i ] a[i] a[i]出现了几次,然后没次根据不同需要,选择循环顺序以及 a s k ask ask求什么,最后把 a [ i ] a[i] a[i]出现的次数+1
前面的数:正序循环
后面的数:倒序循环
比当前这个数小/大: a s k ( a [ i ] − 1 ) / a s k ( m a x x ) − a s k ( a [ i ] ) ask(a[i]-1)/ask(maxx)-ask(a[i]) ask(a[i]1)/ask(maxx)ask(a[i])
经典例题:
楼兰图腾

求顺序

大意是告诉你前面有几个人,问你他是第几个
假如一共有n个人,他前面有k个人,那么就让他站到第k+1个没有人的位置,至于这个位置怎么找,那么就要用上树状数组了,来维护前i个位置有多少个位置没人
经典例题:
L o s t C o w s Lost Cows LostCows
B u y T i c k e t s Buy Tickets BuyTickets

二维数点问题

诶嘿,树状数组可以上二维,具体思想其实就是一个前缀和
例如:求以 ( a , b ) (a,b) (a,b)为左下角, ( c , d ) (c,d) (c,d)为右上角的矩形内的点,可以变成
s u m [ c ] [ d ] − s u m [ a − 1 ] [ d ] − s u m [ c ] [ b − 1 ] + s u m [ a − 1 ] [ b − 1 ] sum[c][d]-sum[a-1][d]-sum[c][b-1]+sum[a-1][b-1] sum[c][d]sum[a1][d]sum[c][b1]+sum[a1][b1]
在此基础上我们利用求逆序对得到的循环规则,用树状数组求解
首先把x排序,这样就可以减少一个影响啦
然后要找的就是当 x = a x=a x=a y < d , y < b y<d,y<b y<d,y<b的数量,当 x = c x=c x=c y < b , y < d y<b,y<d y<b,y<d的数量,用四倍的空间存起来,最后输出答案做个前缀和
所以这是个离线查询哒
经典例题:
园丁的烦恼(板子)
基因序列(这个是和trie树结合,巧妙地运用树的dfn序,进行二维数点)
地道战(把曼哈顿距离转换成切比雪夫距离就可以进行二维数点板子题啦)

前缀后缀求和

这算是树状数组的基础应用,和其他算法结合非常巧妙,当看到<=,>=之类的时候要想到利用树状数组
经典例题:
[SPOJ1825]免费旅行II(在点分治的基础上,运用树状数组进行答案统计)

笛卡尔树

用单调栈实现建树,每棵树满足:根为该子树最小值,且左子树的遍历编号<根<右子树
具体可参见:笛卡尔树

  1. 区间最小值可以考虑一下下哦
    经典例题:
    修数据
    鲤鱼跃龙门
  2. 毕竟是用单调栈建树,单调栈能干的,它也可以
    经典例题:
    L a r g e s t R e c t a n g l e i n a H i s t o g r a m Largest Rectangle in a Histogram LargestRectangleinaHistogram

优先队列

排序

做模拟题的时候很容易让排序找最优解,这时候就能用到堆,当然,重载运算符别忘了怎么写,这里给出代码

struct node 
{
	int x,y,z;
	friend bool operator < (node a1,node a2)//这里只能写<
	{
		return a1.x<a2.y;//这里的符号和真实情况相反,<即为大的在上,>即为小的在上
	}
}
priority_queue<node> q;

经典例题:
模拟交易(太恶心了这题)

可后悔的贪心

如果贪心的时候发现前面的不对了,那么就可以撤销前面一个对结果影响最小的选择,这时候可以直接用堆排序,每次选择完都扔进去,然后就ok了
经典例题:
赌王
作业规划

并查集

模型转换

这个就比较明显了,看到什么谁和谁有关系,就应该往并查集上面去想,还有就是比较不明显的,需要把实在的物体抽象,然后通过每一组的特点进行合并计算
经典例题:
一维弹球(这道题,把球抽象成线段,机关抽象成点,通过两者之间的关心做题,实在是高啊)
同样,这道题也告诉我们,要学会排除或转化题目中没有用的条件,这道题把相互碰撞省掉了(想象成两个球交叉过去走)
例:神奇口袋(一个式子,让题目中给出的 x , y x,y x,y全没用,太强了)

直接跳过某些点

在进行暴力遍历的时候,可能会遍历到一个点多次,不需要,用一个bool数组标记直接跳过,但是还是会遍历到,复杂度依然很高,这时候就能用并查集了!把这些已经遍历过的点全部合并,之后就遍历不到它了,复杂度大大降低!【滑稽】
经典例题:
F r o g    T r a v e l e r Frog\;Traveler FrogTraveler(对于每一个位置,青蛙可能会有多种方式跳到,因为要求的是到达地面的最小天数,如果之前已经跳过了,再跳到相同的位置会浪费天数,所以,第一次是最优的,后面就不管这个点了,于是我们使用并查集,在跳过之后把它并掉就ok了)
清扫积雪 (上题是线性,这个上树了,但是他们的路线是固定的,依然是线性的,值得注意的是,题目中给的是bfs序,求LCA的时候不用再默板子了)
作业规划 (贪心+并查集优化)

trie

可删除

就是给每个节点一个siz,添加的时候siz++,删除的时候siz–,然后在找最大值的时候判断siz是否为空,很巧妙的一个思想
经典例题:
x o r    o n    t r e e xor \;on\; tree xorontree

第二种类型是差不多真的可删除,确实就像可删除线性基一样

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值