
刷题目有段时间了,发现最难得还是模拟。但是也有很多简单问题可以用朴素的空间换时间来大幅加速,看了很多高手的解题报告,发现了这些想法,很典型的是分桶法和树状数组(之后更新了线段树),做一下总结,希望以后自己能活用在其他问题上。
题目是PAT1057 Stack
只是插入和排序找中位数会超时,稍微做变化,有两种方法。
分桶法
使用数轴hash的方法,求前缀和,在这之前再分块便于搜索,用一个数组记录每块有几个数,块长×块数=总数,时间复杂度O(块长+块数)。
类似想法的还有PAT1095 Cars on Campus使用一天的时间轴time[24×60×60],进门axis[intime]++ 出门axis[outime]— 任意时刻的校园内车的数量只要求前缀和就可以了。
|
树状数组
树状数组也是一种快速求前缀和的方法,利用lowbit(i){ i & -i;}求出i的二进制表示中最低位的1所表示的数。
5 & -5 = 0000 0101 & 1111 1011 = 0000 0001 = 1
4 & -4 = 0000 0100 & 1111 1100 = 0000 0100 = 4
如此其实可以将任意一个数用lowbit()将其中的1去掉。
求前7个前缀和:
sum[7]=A[1]+A[2]+A[3]+A[4]+A[5]+A[6]+A[7] ;
C[4]=A[1]+A[2]+A[3]+A[4]; C[6]=A[5]+A[6]; C[7]=A[7];
sum[7]=C[4]+C[6]+C[7];
sum[(111)]=C[(100)]+C[(110)]+C[(111)];

因此自上而下求和,自下而上更新。
|
线段树
线段树在此题可以在logN内求任意区间内的点个数。在此用感觉并不太合适。
这里有两种线段树的实现,普通递归的实现和作为学习摘录的zkw线段树(无递归)。
普通递归
|
zkw线段树
|




近期评论