堆与ST表
堆
堆分为插入,查询,删除3个操作,虽然我们通常用优先队列来实现堆的功能,但是手写堆还是需要会的。
P3378 【模板】堆
最基本的二叉堆,也就是用一个二叉树来模拟的,其中通过一定的单调性来排列,其中堆顶为单调性最高的点位。
类似于现端倪树一般的,我们父节点的左儿子记为now<<1,右儿子为(now<<1)+1。
1.插入
插入的时候,我们把该节点放在堆底,每次与它的父节点比较,看是否需要交换即可。
点击查看代码
heap[++siz]=x;
now=siz;
while(now) {
int nxt=now>>1;
if(heap[nxt]>heap[now]) {
swap(heap[nxt],heap[now]);
now=nxt;
}else {
break;
}
}
2.查询
这个比较简单,直接返回堆顶即可。
return heap[1];
3.删除
对于删除堆顶的需求,我们删除了堆顶,必然就需要补全,可以挑选堆底的一个元素,放在堆顶,与它的左右儿子进行比较,然后判断是否交换。
点击查看代码
swap(heap[siz],heap[1]);
--siz;
now=1;
while((now<<1)<=siz) {
int nxt=now<<1;
if(nxt+1<=siz&&heap[nxt+1]<heap[nxt])
++nxt;
if(heap[nxt]<heap[now]) {
swap(heap[nxt],heap[now]);
now=nxt;
}else {
break;
}
}
ST表
P3865 【模板】ST 表
ST表一般用于求静态区间的最值,其对于长度为\(n\)的数列的初始化复杂度为\(O(NlogN)\),查询复杂度为\(O(1)\)。
我们设一个一维数组\(lg[n]\)和一个二维数组\(f[n][lg[n]]\),其中\(lg[n]\)存储的是为\(n\)取对数并向下取整得到的值,\(f[i][j]\)存的是第\(i\)个数,从它到它后面\(\large 2^j-1\)个数中的最大值。
初始化的方法就已经很显然了,我们从更小的区间来合并即可,\(\large f[i][j]=cal(f[i][j-1],f[i+2^{j-1}][j-1])\),
即\(\large [i,i+2^j-1]\)由\(\large [i,i+2^{j-1}-1]\)和\(\large [i+2^{j-1},i+2^{j}-1]\)合并出答案.
以区间最大值为例,对应代码:
点击查看代码
lg[0]=-1;
for(i=1;i<=n;i++) {
cin>>f[i][0];
lg[i]=lg[i>>1]+1;
// cout<<i<<" "<<lg[i]<<endl;
}
for(int j=1;j<=lg[n];j++) {
for(i=1;i<=n-(1<<j)+1;i++) {
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
点击查看代码
cin>>L>>R;
int k=lg[R-L+1];
cout<<max(f[L][k],f[R-(1<<k)+1][k])<<endl;

浙公网安备 33010602011771号