堆模拟中的映射--个人理解acwing 839

建堆过程中:从下而上是因为你不能不维护上面吧?或者说从上而下不容易对于上面进行维护。

映射用来维护他的下标与插入位次的关系。

假设:|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;
}

纯小白,写这个其实是为了增加自身理解,也锻炼下这方面能力,欢迎指出错误与不足

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值