基础知识:
大顶堆:每个结点的值都大于或等于其左右孩子结点的值
小顶堆:每个结点的值都小于或等于其左右孩子结点的值
二叉堆就是一颗二叉树,是一颗完全二叉树
定义两个操作:
down(int k ):从编号为k的点向下更新
up(int k) :从编号为k的点向上更新
h[]堆数组,size堆当前大小
堆的变化(都可以由上面定义的两个操作来实现):
1.插入一个数 -> h[++ size] = x; up(size)
2.求集合中的最小值 -> h[1]
3.删除最小值 -> h[1] = h[size]; size --; down(1)
4.删除任意一个元素 -> h[k] = h[size]; size --; down(k); up(k);
5.修改任意一个元素 -> h[k] = x; down(k); up(k);
两个操作的具体代码实现(以小根堆为例):
void down (int u)
{
int t = u; //t存储当前位置和左右儿子的最小节点
if (2 * u <= size1 && h[2 * u] < h[t]) t = 2 * u;
if (2 * u + 1 <= size1 && h[2 * u + 1] < h[t]) t = 2 * u + 1;
if (u != t)//如果父节点大于其中的儿子节点需要down操作
{
swap (h[u], h[t]);
down (t);
}
}
void up(int u)
{
while(u/2 && h[u/2]>h[u]) //父结点的值大于儿子节点需要交换
{
h_swap(u/2,u);
u/=2;
}
}
本题只需要up操作
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int in[N], pre[N];
int n, m;
int h[N];
int cnt = 0;
void up (int u)
{
while (u / 2 && h[u] < h[u / 2])
{
swap (h[u], h[u / 2]);
u /= 2;
}
}
int main ()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++)
{
int x; cin >> x;
h[++ cnt] = x;
up (i);
}
map<int, int> mp;
for (int i = 1; i <= n; i ++) mp[h[i]] = i;
while (m --)
{
int x; cin >> x;
string s; cin >> s;
if (s == "is")
{
string s2; cin >> s2;
if (s2 == "the")
{
string s3; cin >> s3;
if (s3 == "root")
{
if (mp[x] == 1)
cout << "T" << "\n";
else
cout << "F" << "\n";
}
else
{
string s4; int x2;
cin >> s4 >> x2;
if (mp[x] == mp[x2] / 2)
cout << "T" << "\n";
else
cout << "F" << "\n";
}
}
else
{
string s3, s4; int x2;
cin >> s3 >> s4 >> x2;
if (mp[x] / 2 == mp[x2])
cout << "T" << "\n";
else
cout << "F" << "\n";
}
}
else
{
int x2;
string s2, s3;
cin >> x2 >> s2 >> s3;
if (mp[x] / 2 == mp[x2] / 2)
cout << "T" << "\n";
else
cout << "F" << "\n";
}
}
}