思路:本题简要的来说就是,让你初始化一个每个节点值都为100的堆,并且他们都有自己各自的编号,然后要有两个功能,第一个功能是能直接指明第n个节点,并且要让他变大或者变小(保证最大堆或者最小堆的基本性质),第二个功能就是查询最大堆和最小堆的根节点。
反思:
1.节点在堆中的编号和题目要求的容易混淆,相当于每个不同的人在固定的岗位上轮换工作,这里我定义了两个数组,分别暗藏与大根堆和小根堆中,他们记录每个节点的真实编号和虚假编号,如person[真实编号]=虚假编号,而我定义了结构体数组,每个节点也记录了自己的真实编号(真实编号是index)
2.切记更新编号时不仅要更新节点的编号,也要更新person的。
3.大根堆和小根堆要完完全全分开来做。
#include<iostream>
#include<math.h>
using namespace std;
const int N = 1001;
int len1 = 0, len2 = 0;
struct node1
{
int val;
int index;
}head1[N];
struct node2
{
int val;
int index;
}head2[N];
int person1[N] = { N };
int person2[N] = { N };
//最小堆
void up_min(int i)
{
while (i != 1 && head1[i].val < head1[i / 2].val)
{
swap(head1[i], head1[i / 2]);
person1[head1[i].index] = i/2;
i = i / 2;
}
}
void down_min(int i)
{
while (i * 2 <= len1)
{
int j = i * 2;
if (j + 1 <= len1 && head1[j].val > head1[j + 1].val)j = j + 1;
if (head1[i].val < head1[j].val) break;
swap(head1[i], head1[j]);
person1[head1[i].index] = j;
i = j;
}
}
//最大堆
void up_max(int i)
{
while (i != 1 && head2[i].val > head2[i / 2].val)
{
swap(head2[i], head2[i / 2]);
person2[head2[i].index] = i/2;
i /= 2;
}
}
void down_max(int i)
{
while (i * 2 <= len2)
{
int j = i * 2;
if (j + 1 <= len2 && head2[j + 1].val > head2[j].val)j++;
if (head2[i].val > head2[j].val) break;
swap(head2[i], head2[j]);
person2[head2[i].index] = j;
i = j;
}
}
void min_(int i,int x)
{
if (x == 0) return;
if (x < 0)up_min(i);
if (x > 0)down_min(i);
}
void max_(int i, int x)
{
if (x == 0) return;
if (x < 0)down_max(i);
if (x > 0)up_max(i);
}
int main()
{
int n;cin >> n;
while (n--)
{
head1[++len1].val = 100;
head1[len1].index = len1;
person1[len1] = len1;
head2[++len2].val = 100;
head2[len2].index = len2;
person2[len2] = len2;
}
int m;cin >> m;
while (m--)
{
int z=0;
cin >> z;
if (z == 1)
{
int p, x;cin >> p >> x;
head1[person1[p]].val += x;
min_(person1[p], x);
head2[person2[p]].val += x;
max_(person2[p], x);
}
if (z == 2)
{
cout << head2[1].val;
cout << head1[1].val;
}
}
return 0;
}