建堆过程中:从下而上是因为你不能不维护上面吧?或者说从上而下不容易对于上面进行维护。
映射用来维护他的下标与插入位次的关系。
假设:|A数组:用来存储他的下标与插入位次关系,B数组用来存插入位次与下标关系.|
s是被操作的数组.
big_swap(a,b)
{
swap(A[B[a]],A[B[b]]);
swap(B[a],B[b]);
swap(s[a],s[b]);
}
对于交换:
1.交换他们插入位次所代表的下标(这个就需要B来进行转化了,因为你不知道这个下标代表的插入位次,在所写代码中你传入的只是这个下标位置。)
2.交换下标存的插入位次(这个数换位置了,然后他的下标换了,但是换的只是下标存储数,它存的插入位次也得换)
3.换下标存储数.
下标存储数直接转换并不与AB数冲突,因为AB就是来维护这个的。每个下标所存在的位置不会被改变,被改变的只是这个下标所存储的值B[a],s[a]之类。
#define N 100100
int s[N];
int it[N], ti[N];
int idx;
int cnt;
void HP(int t1, int t2)
{
swap(it[ti[t1]], it[ti[t2]]);
swap(ti[t1], ti[t2]);
swap(s[t1], s[t2]);
}
void down(int i)
{
int sm = i;
int l = i * 2;
int r = i * 2 + 1;
if (l<=cnt && s[sm]>s[l])sm = l;
if (r<=cnt && s[sm]>s[r])sm = r;
if (sm != i)
{
HP(sm, i);
down(sm);
}
}
void up(int i)
{
while (i / 2 && s[i] < s[i/ 2])
{
HP(i, i/ 2);
i = i/ 2;
}
}
int main()
{
int n;
cin >> n;
while (n--)
{
string t;
cin >> t;
if (t == "I") //插入建堆
{
int x;
cin >> x;
idx++;
cnt++;
s[cnt] = x;
ti[cnt] = idx;
it[idx] = cnt;
up(cnt);
}
else if (t == "PM")
{
cout << s[1]<<endl;
}
else if (t == "DM")
{
HP(1, cnt);
cnt--;
down(1);
}
else if (t == "D")
{
int k;
cin >> k;
k = it[k];
HP(k, cnt);
cnt--;
up(k);
down(k);
}
else
{
int k,x;
cin >>k>> x;
k = it[k];
s[k] = x;
up(k);
down(k);
}
}
return 0;
}
纯小白,写这个其实是为了增加自身理解,也锻炼下这方面能力,欢迎指出错误与不足