• 蒟篛的P1334 瑞瑞的木板 题解(合并果子也是可以这样做的)


    /*

    本题是一个比较简单的堆排序的题目,

    思想和之前的合并果子非常像(简直一模一样) 我每次找到数列中最小的俩个进行合并,

    再将合并后的数存入数列中 (可以用堆实现,大佬可以无视直接用优先队列,原理是一样的,

    我们建立一个二叉树,让每个子节点都大于它的父亲节点 二叉树的根节点就成了最小值)

    再找新的数列中最小的俩个;

    (以此类推,并将过程中找到的合并后的值加起来就是答案)

    */

    #include<bits/stdc++.h>

    using namespace std;

    int n;

    long long l,s[50000],da;//题目数字给的太大了,不开long long过不了。

    void sf(int wz)//上浮,将一个新值按规矩上移(每个子节点都大于它的父亲节点)

    {

      while(wz!=1)//到顶结束

      {

        int cnm=wz>>1;//位运算,相当于除以2(向下取);

        if(s[wz]<s[cnm])

           swap(s[wz],s[cnm]);

        else//找到自己位置也可以结束

          break;

         wz=cnm;

      }

    }

    void xc()//下沉,将一个较大值按规矩下移(顺便找到新的最小)

    {

      int wz=1;

      while((wz<<1)<=n)

      {

        int cnm=wz<<1;//相当于乘2

         int t=wz;//t表示我当前的值和t的值交换

        if(cnm<=n&&s[wz]>s[cnm])

          t=cnm;//有左边并且可换

        if(s[wz]>s[cnm+1]&&s[cnm]>s[cnm+1]&&cnm+1<=n)

          t=cnm+1;//有右边并且比左边好

        if(t!=wz)//不等交换

          swap(s[wz],s[t]);

         else//找到位置,不动了

          ·break;

         wz=t;

      }

    }

    int main()

    {

      cin>>n;

      for(int i=1;i<=n;i++)

      {

        cin>>l;

        s[i]=l;//表示我新进来一个数,我先暂时把它放在完全二叉树末尾(也就是第i个)

        sf(i);//我要把树中第i个点的数按要求上浮(上小下大)

      }

      for(int i=1;n!=1;i++)//当我节点个数为1时就做完了

      {

        int k=s[1];//取一个最小

        s[1]=s[n--];//将这个最小变为一个较大值

        xc();//把这个较大值下沉(相当于去掉最小,重新找最小)

        k=k+s[1];//再取

        s[1]=s[n--];//再删

        xc();

        s[++n]=k;//将新值存入完全二叉树末尾

        sf(n);//再次上浮

        da=da+k;//累计答案

      }

      cout<<da;

    }

  • 相关阅读:
    【网络游戏同步技术】帧同步的一致性
    【C++】STL常用容器总结之五:双端队列deque
    使 egg-multipart 同时支持 stream 和 file
    react + 图灵api 实现模拟客服
    egg 扩展上传文件白名单
    input[type=file] 样式美化,input上传按钮美化
    react-lazyload 实现图片懒加载
    useEffect 模拟 react 生命周期
    egg 实现下载数据,并保存成excel文件
    egg 实现上传excel,并解析保存到数据库
  • 原文地址:https://www.cnblogs.com/ren-meng-hua-qi/p/9108637.html
Copyright © 2020-2023  润新知