7-1 Arrays and Linked Lists (20 分)
Let’s design a data structure A that combines arrays and linked lists as the following:
At the very beginning, an integer array
A
0
A_0
A0 of length
L
0
L_0
L0 is initialized for the user. When the user tries to access the ith element
A
[
i
]
A[i]
A[i], if
0
≤
i
<
L
0
0≤i<L_0
0≤i<L0, then
A
[
i
]
A[i]
A[i] is just
A
0
[
i
]
A_0[i]
A0[i]. Now our system is supposed to return
h
0
+
i
×
s
i
z
e
o
f
(
i
n
t
)
h_0 + i × sizeof(int)
h0+i×sizeof(int) as the accessed address, where
h
0
h_0
h0 is the initial address of
A
0
A_0
A0 , and
s
i
z
e
o
f
(
i
n
t
)
sizeof(int)
sizeof(int) 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
≥
L
0
i ≥ L_0
i≥L0), our system will declare another array
A
1
A_1
A1 of length
L
1
L_1
L1. Now
A
[
i
]
A[i]
A[i] corresponds to
A
1
[
j
]
A_1[j]
A1[j] (It’s your job to figure out the relationship between
i
i
i and
j
j
j). If
0
≤
j
<
L
1
0 ≤ j < L_1
0≤j<L1 , then
h
1
+
j
×
s
i
z
e
o
f
(
i
n
t
)
h_1 + j × sizeof(int)
h1+j×sizeof(int) is returned as the accessed address, where
h
1
h_1
h1 is the initial address of
A
1
A_1
A1.
And if there is yet another overflow of the user’s access to
A
1
[
j
]
A_1[j]
A1[j], our system will declare another array
A
2
A_2
A2 of length
L
2
L_2
L2, and so on so forth.
Your job is to implement this data structure and to return the address of any access.
Input Specification:
Each input file contains one test case. For each case, the first line gives 2 positive integers
N
N
N (
≤
1
0
4
≤ 10^4
≤104) and
K
K
K (
≤
1
0
3
≤ 10^3
≤103) which are the number of arrays that can be used, and the number of user queries, respectively.
Then
N
N
N lines follow, each gives 2 positive integers, which are the initial address (
≤
1
0
7
≤ 10^7
≤107) and the length (
≤
100
≤ 100
≤100) of an array, respectively. The numbers are separated by spaces. It is guaranteed that there is no overlap of the spaces occupied by these arrays.
Finally,
K
K
K indices of the elements queried by users are given in the last line. Each index is an integer in the range
[
0
,
2
20
]
[0, 2^{20}]
[0,220].
Output Specification:
For each query, print in a line the accessed address. If the queried index exceeds the range of all the
N
N
N arrays, output “
I
l
l
e
g
a
l
A
c
c
e
s
s
Illegal~Access
Illegal Access” instead, and this query must NOT be processed.
Print in the last line the total number of arrays that have been declared for the whole process.
Sample Input:
6 7
2048 5
128 6
4016 10
1024 7
3072 12
9332 10
2 12 25 50 28 8 39
Sample Output:
2056
4020
1040
Illegal Access
3072
140
3116
5
Hint:
A
[
2
]
A[2]
A[2] is just
A
0
[
2
]
A_0[2]
A0[2], so the accessed address is
2048
+
2
×
4
=
2056
2048 + 2 × 4 = 2056
2048+2×4=2056.
In order to access
A
[
12
]
A[12]
A[12], declaring
A
1
A_1
A1 is not enough, we need
A
2
A_2
A2 with initial address
h
2
=
4016
h_2 = 4016
h2=4016. Since
A
[
12
]
=
A
2
[
1
]
A[12] = A_2[1]
A[12]=A2[1], the accessed address is
4016
+
1
×
4
=
4020
4016 + 1 × 4 = 4020
4016+1×4=4020.
In order to access
A
[
25
]
A[25]
A[25], we need
A
3
A_3
A3 with initial address
h
3
=
1024
h_3 = 1024
h3=1024. Since
A
[
25
]
=
A
3
[
4
]
A[25] = A_3[4]
A[25]=A3[4], the accessed address is
1024
+
4
×
4
=
1040
1024 + 4 × 4 = 1040
1024+4×4=1040.
The access of
A
[
50
]
A[50]
A[50] exceeds the maximum boundary of all the arrays, and hence an illegal access. There is no extra array declared.
In order to access
A
[
28
]
A[28]
A[28], we need
A
4
A_4
A4 with initial address
h
4
=
3072
h_4 = 3072
h4=3072. Since
A
[
28
]
=
A
4
[
0
]
A[28] = A_4[0]
A[28]=A4[0], the accessed address is just
3072
3072
3072.
It is clear to see that
A
[
8
]
=
A
1
[
3
]
A[8] = A_1[3]
A[8]=A1[3] and hence the accessed address is
128
+
3
×
4
=
140
128 + 3 × 4 = 140
128+3×4=140; and
A
[
39
]
=
A
4
[
11
]
A[39] = A_4[11]
A[39]=A4[11] so the accessed address is
3072
+
11
×
4
=
3116
3072 + 11 × 4 = 3116
3072+11×4=3116.
All together there are 5 arrays used for the above queries.
满分题解
/**
* 题目:PAT_A实战-过程模拟-中等-2021秋-模拟动态数组
*
* 说明:
* 1. 输入:整数n,k, n行数组起始地址与数组长度,一行k个查询的数组下标
* 2. 任务:输出每个查询位置的地址
* 3. 输出:每个查询位置的地址
*
* 技巧:
* 1. 比赛当时做完后,发现未满分者这题没AC的最多,说明多少有点坑;但是细心做发现其实很简单
* 甚至没什么极端输入,边界也没有看上去那么难区分
*
*/
#include<iostream>
#include<cstring>
using namespace std;
#define MAXN 10009
#define MAXK 1009
typedef long long LL_t; /* 看到2 ^ 20就全long long了,实际上int应该是完全够用的 */
int n, k;
LL_t adi[MAXN]; /* 数组i的起始地址:address of initial element of every array */
LL_t lena[MAXN]; /* 数组i的长度:length of arrary */
LL_t pos[MAXN]; /* 若index属于左闭右开区间[pos[j], pos[j + 1]), 那么index应存放与数组j, 0 <= j < n */
LL_t iq; /* 每轮输入的index: index of query */
int vis[MAXN]; /* 标记第i个数组是否被启用 */
int main(void)
{
cin >> n >> k;
pos[0] = 0;
for (int i = 0; i < n; ++i) {
cin >> adi[i];
cin >> lena[i];
if (i == 0) {
pos[i] = 0;
}
else { /* 构造pos[]类似前缀和,但不完全一样 */
pos[i] = pos[i - 1] + lena[i - 1];
}
}
if (n > 0) {
pos[n] = pos[n - 1] + lena[n - 1];
}
memset(vis, 0, sizeof(vis));
vis[0] = 1; /* 起始数组一定会启用 */
for (int i = 0; i < k; ++i) {
cin >> iq;
bool ok = false;
for (int j = 0; j < n; ++j) {
if (iq >= pos[j] && iq < pos[j + 1]) {
if (vis[j] == 0) {
vis[j] = 1;
}
ok = true;
cout << adi[j] + (iq - pos[j]) * 4 << endl;
break;
}
}
if (!ok) {
cout << "Illegal Access\n";
}
}
int cnt = 0;
for (int i = 0; i < n; ++i) { /* 应该是本题唯一坑点:若靠后数组被启用,则它之前的数组都要被启用 */
if (vis[i] == 1 && cnt < i + 1) {
cnt = i + 1;
}
}
if (n == 0) {
cout << 1;
}
else {
cout << cnt;
}
return 0;
}