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, i≥L0), 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.
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越辦越好!