PAT甲级真题1171 Replacement Selection(置换选择) 双解法 带注释

这篇具有很好参考价值的文章主要介绍了PAT甲级真题1171 Replacement Selection(置换选择) 双解法 带注释。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

置换选择排序分析
手写小根堆
解法一:手写小根堆 模拟

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
using namespace std;
/*
对于所有输入
先将前m个数 存入小根堆
从第m+1个数开始遍历 
设t为小根堆堆顶 cnt为小根堆内元素数量
idx代表当前归并段编号 a[i]为当前遍历到的数
如果a[i]>=t 意味着a[i]可以并入当前归并段
t弹出存入当前归并段 a[i]存入小根堆

如果a[i]<t 意味着a[i]属于下一个归并段
t弹出存入当前归并段 a[i]存储在小根堆之外
注意 此时小根堆内的元素数量cnt-=1

我们每一轮都要弹出小根堆堆顶
但是 由于a[i]<t的情况存在 cnt是会归零的
意味着没有元素可以弹出了
此时 存储在小根堆之外的元素 就可以组成一个新的小根堆
他们属于同一个归并段 idx++

因此 在每一次弹出小根堆堆顶前 都要检查小根堆是否为空
若为空 将存在小根堆之外的数组成一个小根堆,idx++

这里提供一个偷鸡的实现方式
heap[1]=heap[cnt--],down(1)//实现堆顶元素的弹出
heap[cnt+1]=a[i]//还是存在heap数组 但是不在小根堆内
然后对于cnt=0的时候 要将其组成一个小根堆
for(int i=cnt/2;i>=1;i--) down(i)
进行初始化就好了
*/
int n,m;
int a[100010];
int mp[100010];
int heap[100010],cnt;
void down(int u){
    int t=u;
    if (u*2<=cnt&&heap[t]>heap[u*2]) t=u*2;
    if (u*2+1<=cnt&&heap[t]>heap[u*2+1]) t=u*2+1;
    if (t!=u) {
        swap(heap[u],heap[t]);
        down(t);
    }
}
void up(int u){
    while (u>1&&heap[u]<heap[u/2]) {
        swap(heap[u],heap[u/2]);
        u/=2;
    }
}
int main (){
    scanf("%d%d", &n,&m);
    for (int i=1;i<=n;i++) {
        scanf ("%d",&a[i]);
        if (i<=m) {//插入堆
            heap[++cnt]=a[i];
            up(cnt);
        }
    }
    int idx=0;//
    int last;
    vector<vector<int>> ans(100010);//答案存储在这个二维数组 idx为下标
    for (int i=m+1;i<=n;i++){
        if (!cnt) {//因为每一轮都要弹出 所以要进行判断
            cnt=m,idx++;
            for (int i=cnt/2;i>=1;i--) down(i);
        }
        int t=heap[1];//堆顶
        if (a[i]>=t) {//a[i]是本归并段
            heap[1]=a[i],down(1);//a[i]插入小根堆
//实际上是将a[i]放在弹出后空缺的堆顶 因此cnt无变化
        }
        else {//a[i]是下一个归并段的
            heap[1]=heap[cnt--],down(1);//弹出堆顶
            heap[cnt+1]=a[i];//a[i]存在小根堆之外
        }
        ans[idx].push_back(t);//t都是存入当前归并段的
    }
//此时循环结束 还有m个数在heap数组中
//其中1~cnt同属一个归并段 但是是否与idx为一个归并段不清楚 
//cnt+1~m属于1~cnt后面的归并段
    if (!cnt) {//涉及heap[1]是否属于当前归并段 看cnt
        cnt=m,idx++;
        for (int i=cnt/2;i>=1;i--) down(i);
    }
    for (int i=1;i<=cnt;i++) ans[idx].push_back(heap[i]);
    if (cnt<m) idx++;//cnt+1~m属于1~cnt后面的归并段
    for (int i=cnt+1;i<=m;i++) ans[idx].push_back(heap[i]);
    
    for (int i=0;i<=idx;i++){//输出答案 注意回车空格
        if (i)puts("");
        sort(ans[i].begin(),ans[i].end());
        for (int j=0;j<ans[i].size();j++){
            if (j) printf (" ");
            printf ("%d",ans[i][j]);
        }
    }
    return 0;
}

解法二:双数组存储模拟
参考自文章来源地址https://www.toymoban.com/news/detail-774583.html

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
#include <queue>
using namespace std;
// 对于一个序列中的数 其不是当前归并段就是下一个归并段的
// 以弹出数的数量为标记
// 每一轮以是否遍历完了原始序列进行判断
// 未遍历完 将a[i]存入对应归并段
// 每一轮都将堆顶存入now归并段
// 操作完后检查堆是否为空
// 若为空 说明当前归并段气数已尽
// 将next归并段全部存入小根堆
// next now数组clear
// 新的循环开始
int n,m;
int a[100010];
priority_queue <int,vector<int>,greater<int>> q;
int main (){
    scanf("%d%d", &n,&m);
    for (int i=1;i<=n;i++) scanf ("%d",&a[i]);
    for (int i=1;i<=m;i++) q.push(a[i]);
    vector <int> now,next;//本归并段 下一个归并段
    int cnt=0;
    int idx=m+1;
    while (cnt<n){
        int t=q.top();
        q.pop();
        cnt++;
        now.push_back(t);
        if (idx<=n){//数组未遍历完
            if (t<=a[idx]) {//属于一个归并段 存入堆
                q.push(a[idx++]);
            }
            else {//属于下一个归并段
                next.push_back(a[idx++]);
            }
        }
        if (q.empty()){//恒纪元已经结束嘞!
            sort(now.begin(),now.end());
            for (int i=0;i<now.size();i++){//输出本轮
                if (i) printf (" ");
                printf ("%d",now[i]);
            }
            printf ("\n");
            now.clear();
            for (auto x:next) q.push(x);
            next.clear();
        }
    }
    return 0;
}

到了这里,关于PAT甲级真题1171 Replacement Selection(置换选择) 双解法 带注释的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 菜鸟记录PAT甲级1003--Emergency

    久违的PAT,由于考研408数据结构中有一定需要,同时也是对先前所遗留的竞赛遗憾进行一定弥补 ,再次继续PAT甲级1003.。 As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the l

    2023年04月13日
    浏览(25)
  • 1111 Online Map (PAT甲级)

    这道题我读题不仔细导致踩了个大坑,一个测试点过不了卡了好几个小时:第二个dijkstra算法中,题目要求是“In case the fastest path is not unique, output the one that passes through the fewest intersections”,我却想当然地认为在fastest path is not unique的时候,判断标准是最短距离…… Input our

    2024年02月07日
    浏览(31)
  • 1083 List Grades (PAT甲级)

    Given a list of N student records with name, ID and grade. You are supposed to sort the records with respect to the grade in non-increasing order, and output those student records of which the grades are in a given interval. Input Specification: Each input file contains one test case. Each case is given in the following format: where  name[i]  and  ID[i

    2024年02月08日
    浏览(41)
  • 1072 Gas Station (PAT甲级)

    A gas station has to be built at such a location that the minimum distance between the station and any of the residential housing is as far away as possible. However it must guarantee that all the houses are in its service range. Now given the map of the city and several candidate locations for the gas station, you are supposed to give the best recommendatio

    2024年02月09日
    浏览(28)
  • PAT甲级图论相关题目

    PAT甲级图论相关题目: 分数 25 As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some o

    2024年01月21日
    浏览(40)
  • 1114 Family Property (PAT甲级)

    This time, you are supposed to help us collect the data for family-owned property. Given each person\\\'s family members, and the estate(房产)info under his/her own name, we need to know the size of each family, and the average area and number of sets of their real estate. Input Specification: Each input file contains one test case. For each case, the fir

    2024年02月06日
    浏览(38)
  • 1021 Deepest Root (PAT甲级)

    1021. Deepest Root (25)-PAT甲级真题(图的遍历,dfs,连通分量的个数)_柳婼的博客-CSDN博客 柳婼的解法在这里,两次dfs,还是挺好玩的。 我的解法比较暴力,就是先用并查集算连通分量(这个其实还是dfs来算会更方便),如果只有一个连通分量,那deepest root一定在仅有一条arc的

    2024年02月15日
    浏览(22)
  • PAT 甲级【1007 Maximum Subsequence Sum】

    本题是考察动态规划与java的快速输入: max[i]表示第i个结尾的最大的连续子串和。b begin[i]表示第[begin[i],i]为最大和的开始位置 超时代码: 未超时: 能用动态规划解决的问题,需要满足三个条件:最优子结构,无后效性和子问题重叠。 具有最优子结构也可能是适合用贪心的

    2024年02月08日
    浏览(31)
  • 1074 Reversing Linked List (PAT甲级)

    Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5→6. Input Specification: Each input file contains one test case. For each case, the first line

    2024年02月09日
    浏览(32)
  • PAT 甲级1005【1005 Spell It Right】

    用JAVA可以用BigInteger解决。       太长不看版:结尾自取模板…… 高精度计算(Arbitrary-Precision Arithmetic),也被称作大整数(bignum)计算,运用了一些算法结构来支持更大整数间的运算(数字大小超过语言内建整型)。 高精度问题包含很多小的细节,实现上也有很多讲究。

    2024年02月08日
    浏览(67)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包