PAT甲级-2021秋-第1题-模拟动态数组-AC代码

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 0i<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 iL0), 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 0j<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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XtionDoubleAI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值