2021秋季PAT甲级考试题解

2021PAT秋季甲级考试题解

1001 Arrays and Linked Lists

题意

Let's design a data structure A that combines arrays and linked lists as the following:

At the very beginning, an integer array A0 of length L0 is initialized for the user. When the user tries to access the ith element A[i], if 0≤i<L0, then A[i] is just A0[i]. Now our system is supposed to return h0+i×sizeo**f(in**t) as the accessed address, where h0 is the initial address of A0, and sizeo**f(in**t) is the size of the array element, which is simply int, taking 4 bytes.

In case there is an overflow of the user's access (that is, iL0), our system will declare another array A1 of length L1. Now A[i] corresponds to A1[j] (It's your job to figure out the relationship between i and j). If 0≤j<L1, then h1+j×sizeo**f(in**t) is returned as the accessed address, where h1 is the initial address of A1.

And if there is yet another overflow of the user's access to A1[j], our system will declare another array A2 of length L2, and so on so forth.

Your job is to implement this data structure and to return the address of any access

案例:

6 7
2048 5
128 6
4016 10
1024 7
3072 12
9332 10
2 12 25 50 28 8 39

答案:

2056
4020
1040
Illegal Access
3072
140
3116
5

上面有些地方粘过来没改格式。这道题从类型上来说是模拟题,题目给定n个Array,每个Array有一个首地址和长度,然后K个询问,每个询问有一个位置,问这个位置在Array中的结束地址在哪或者不合法,然后问开了几个数组,具体还有些要求。举个例子,第二个询问是12,因为第一个和第二个总共才10,注意数组下标从0开始,因此12第三个数组的第一个位置。

这道题有几个坑点:1.数组要连续开,例如我们问的地址在第三个数组,那么需要从1一直开到3。2.第一个数组初始开启,也就是最少1

题解

观察数据复杂度是在1e7左右,直接暴力遍历即可,把每个位置属于哪个数组计算出来,然后减去当前数组的开头计算答案即可。在过程中维护最大值表示开的数组。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e7+10;
ll sum[N];
ll a[N],b[N];
ll st[N];
ll be[N];
int main(){
    ll n,k;
    cin>>n>>k;
    ll i;
    for(i=1;i<=n;i++){
        cin>>a[i]>>b[i];
    }
    ll l=0;
    for(i=1;i<=n;i++){
        be[i]=l;
        for(ll j=1;j<=b[i];j++){
            st[l]=i;
            l++;
        }
    }
    ll mx=1;
    for(i=1;i<=k;i++){
        ll x;
        cin>>x;
        ll pos=st[x];
        if(!pos){
            cout<<"Illegal Access"<<endl;
            continue;
        }
        mx=max(mx,pos);
        cout<<a[pos]+4*(x-be[pos])<<endl;
    }
    cout<<mx<<endl;
}

1002 Stack of Hats

题意

PATers believe that wearing hats makes them look handsome, so wherever they go, everyone of them would wear a hat. One day they came to a restaurant, a waiter collected their hats and piled them up. But then when they were ready to leave, they had to face a stack of hats as shown by the above figure. So your job is to help them line up so that everyone can pick up his/her hat one by one in order without any trouble.

It is known that every hat has a unique size, which is related to the weight of its owner -- that is, the heavier one wears larger hat.

案例:

10
12 19 13 11 15 18 17 14 16 20
67 90 180 98 87 105 76 88 150 124

答案:

3 4 8 6 10 2 1 5 9 7

题目给了n个帽子的大小,和n个人的体重,体重大的人带重帽子,按顺序询问每顶帽子被谁带

题解

本质上是排序模拟题,只要用结构体数组存id和数据之后按大小排序即可

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct node{
    int x,id;
}s[N],g[N];
bool cmp(node a,node b){
    return a.x>b.x;
}
int ans[N];
int main(){
    int n;
    cin>>n;
    int i;
    for(i=1;i<=n;i++){
        cin>>s[i].x;
        s[i].id=n-i+1;
    }
    for(i=1;i<=n;i++){
        cin>>g[i].x;
        g[i].id=i;
    }
    sort(s+1,s+1+n,cmp);
    sort(g+1,g+1+n,cmp);
    for(i=1;i<=n;i++){
        ans[s[i].id]=i;
    }
    for(i=1;i<=n;i++){
        int x=ans[i];
        if(i==1)
        cout<<g[x].id;
        else
            cout<<" "<<g[x].id;
    }
}

1003 Playground Exploration

题意

A playground is equipped with ball pits and tents connected by tunnels. Kids can crawl through the tunnels to meet their friends at a spot with a tent or a ball pit.

Now let's mark each meeting spot (a tent or a ball pit) by a number. Assume that once a kid starts to explore the playground from any meeting spot, he/she will always choose the next destination with the smallest number, and he/she would never want to visit the same spot twice. Your job is to help the kids to find the best starting spot so they can explore as many spots as they can.

案例:

8 10
1 2
3 4
5 8
1 4
6 1
3 7
2 4
5 3
2 8
2 5

答案:

6 7

某人可以从任何点出发,但是每次都要找最小且没走过的点走,问最长能走多少,并且询问起点

题解

一道模拟题,观察到数据很小,只要模拟从每个点开始走一遍即可。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int dis[N];
int st[110];
vector<int> g[N];
int main(){
    int n,m;
    cin>>n>>m;
    int i;
    memset(dis,0x3f,sizeof dis);
    for(i=1;i<=m;i++){
        int a,b;
        cin>>a>>b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    int mx=0;
    int pos=0;
    for(i=1;i<=n;i++)
        sort(g[i].begin(),g[i].end());
    for(i=1;i<=n;i++){
        int cnt=0;
        int l=i;
        memset(st,0,sizeof st);
        cnt=1;
        st[l]=1;
        while(1){
            int flag=0;
            for(int j=0;j<g[l].size();j++){
                int x=g[l][j];
                if(!st[x]){
                    flag=1;
                    st[x]=1;
                    cnt++;
                    l=x;
                    break;
                }
            }
            if(!flag){
                break;
            }
        }
        if(cnt>mx){
            mx=cnt;
            pos=i;
        }
    }
    cout<<pos<<" "<<mx<<endl;
}

1004 Sorted Cartesian Tree

题意

A Sorted Cartesian tree is a tree of (key, priority) pairs. The tree is heap-ordered according to the priority values, and an inorder traversal gives the keys in sorted order. For example, given the pairs { (55, 8), (58, 15), (62, 3), (73, 4), (85, 1), (88, 5), (90, 12), (95, 10), (96, 18), (98, 6) }, the increasing min-heap Cartesian tree is shown by the figure.

2021秋季PAT甲级考试题解

Your job is to do level-order traversals on an increasing min-heap Cartesian tree.

案例:

10
88 5
58 15
95 10
62 3
55 8
98 6
85 1
90 12
96 18
73 4

答案:

85 62 88 55 73 98 58 95 90 96
1 3 5 8 4 6 15 10 12 18

给一些pair,假设first是key,second是priority。建一棵树,使得按中序遍历所得的key是递增的,且priority满足小顶堆。求这棵树的层序遍历

题解

树的套路题,pat考试很喜欢考。本题给的数据并不是按key排好序的,因此先按key排一下序。然后我们发现,由于满足小顶堆,因此区间最靠左的最小值肯定是根,题目没说明priority唯一,这样我们只需要按一直按照这样的手法进行dfs划分两边,就能求出每个点的左儿子和右儿子,之后bfs输出一下就行。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct node{
    int a,b;
}s[N];
int L[N],R[N];
int st[110];
bool cmp(node a,node b){
    return a.a<b.a;
}
int dfs(int l,int r){
    if(r<l)
        return 0;
    int i;
    int rt=l;
    for(i=l;i<=r;i++){
        if(s[i].b<s[rt].b){
            rt=i;
        }
    }
    L[rt]=dfs(l,rt-1);
    R[rt]=dfs(rt+1,r);
    return rt;
}
void bfs(int u){
    queue<int> q;
    vector<int> num1;
    vector<int> num2;
    q.push(u);
    while(q.size()){
        int t=q.front();
        q.pop();
        num1.push_back(s[t].a);
        num2.push_back(s[t].b);
        //cout<<L[t]<<" "<<R[t]<<endl;
        //cout<<s[L[t]].b<<" "<<s[R[t]].b<<endl;
        if(L[t])
            q.push(L[t]);
        if(R[t])
            q.push(R[t]);
    }
    for(int i=0;i<num1.size();i++){
        if(i){
            cout<<" "<<num1[i];
        }
        else{
            cout<<num1[i];
        }
    }
    cout<<endl;
    for(int i=0;i<num2.size();i++){
        if(i){
            cout<<" "<<num2[i];
        }
        else{
            cout<<num2[i];
        }
    }
}
int main(){
    int n;
    cin>>n;
    int i;
    for(i=1;i<=n;i++){
        cin>>s[i].a>>s[i].b;
    }
    sort(s+1,s+1+n,cmp);
    int rt=dfs(1,n);
    bfs(rt);
}

个人总结

这次秋季PAT开考前出了点事故,考后424个满分,题目难度比较低,相对于前几次来说,据说第四题是19冬季原题。由于某些众所周知的原因,大概这是我最后一次参加PAT了,本来打算明年去玩一下*。从题型来说,模拟题太多,但不需要太多码力。从结果来看,区分度不太够,现在的学生水平已经提升很快,PAT甲级的难度已经很难满足学生的需求了。其实可以考虑加大思维难度,进行一些合理结合。有合理区分度的比赛更有含金量,个人感觉更能吸引同学来参与,特别是在后浙大机试时代hh。祝PTA越办越好!

上一篇:Codeforces Round #558 (Div. 2)


下一篇:【English】20190326