D. Array Repetition
D. Array Repetition
Jayden has an array which is initially empty. There are operations of two types he must perform in the given order.
- Jayden appends an integer () to the end of array .
- Jayden appends copies of array to the end of array . In other words, array becomes . It is guaranteed that he has done at least one operation of the first type before this.
Jayden has queries. For each query, you must tell him the -th element of array . The elements of the array are numbered from .
Input
Each test consists of multiple test cases. The first line contains a single integer () — the number of test cases. The description of the test cases follows.
The first line of each test case contains two integers and () — the number of operations and the number of queries.
The following lines describe the operations. Each line contains two integers and (), where denotes the type of operation. If , then () is the integer Jayden appends to the end of the array. If , then () is the number of copies Jayden appends to the end of the array.
The next line of each test case contains integers (), which denote the queries, where is the size of the array after finishing all operations.
It is guaranteed that the sum of and the sum of over all test cases does not exceed .
Output
For each test case, output integers — answers to Jayden's queries.
Example
input
4
5 10
1 1
1 2
2 1
1 3
2 3
1 2 3 4 5 6 14 15 16 20
10 10
1 3
1 8
2 15
1 6
1 9
1 1
2 6
1 1
2 12
2 10
32752 25178 3198 3199 2460 2461 31450 33260 9016 4996
12 5
1 6
1 11
2 392130334
1 4
2 744811750
1 10
1 5
2 209373780
2 178928984
1 3
2 658326464
2 1000000000
914576963034536490 640707385283752918 636773368365261971 584126563607944922 1000000000000000000
2 2
1 1
1 2
1 2
output
1 2 1 2 3 1 2 3 1 3
9 8 1 3 1 3 6 3 8 8
11 11 11 10 11
1 2
Note
In the first test case:
- After the first operation ;
- After the second operation ;
- After the third operation ;
- After the fourth operation ;
- After the fifth operation .
In the fourth test case, after all operations .
解题思路
首先我们不可能根据操作把数组 模拟建出来,否则时间和空间复杂度都会爆掉,意味着一定是通过“压缩”的方式来存储数组 的信息。
考虑用链式结构依次存储每个状态 的信息,那么每个节点存储哪些参数呢?对于操作 ,显然要记录拷贝前 的大小(也就是当前 的大小),记作 ,以及拷贝后的数量 ,记作 。这样对于当前节点的两个参数 与 ,就可以得知当前的 是将前一个节点所表示的数组拷贝 份得到的,大小为 。
另外对于操作 ,我们还需要在节点中记录数组的最后一个元素是什么,如果有连续的操作 ,为了避免开额外的节点我们在节点中用一个 std::vector
来记录连续的操作 压入的元素,只有在操作 时才开新的节点。由于询问的下标不超过 这样做就可以保证在 次操作后节点的数量不超过 个(因为 ,同时当数组 的大小不超过 才执行操作)。
因此新的节点的参数 就是前一个节点的 , 是std::vector
的大小。另外只有在当前数组大小不超过 时才进行拷贝,同时还要保证拷贝后的数组大小不超过 ,即新节点的参数 实际上应该是 ,这里的 是新节点的。
对于询问 ,只需从后往前依次枚举每个节点,对于当前节点状态的数组,记 ,表示上一个状态的数组拷贝了 份后的大小。如果 ,那么很明显答案就是 。否则 的位置在某份拷贝的数组中(即大小为 的数组),令 ,得到其所在拷贝的数组的下标,然后遍历到前一个节点用同样的方法继续处理。
AC 代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
struct Node {
LL sz, c;
vector<int> q;
};
void solve() {
int n, m;
cin >> n >> m;
vector<Node> p({{0}});
while (n--) {
int op, x;
cin >> op >> x;
if (op == 1) {
p.back().q.push_back(x);
}
else {
LL sz = p.back().sz * p.back().c + p.back().q.size();
if (sz < (LL)1e18) p.push_back({sz, min(x + 1ll, ((LL)1e18 + sz - 1) / sz)});
}
}
while (m--) {
LL x;
cin >> x;
for (int i = p.size() - 1; i >= 0; i--) {
LL sz = p[i].sz * p[i].c;
if (x > sz) {
cout << p[i].q[x - sz - 1] << ' ';
break;
}
else {
x = (x - 1) % p[i].sz + 1;
}
}
}
cout << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
参考资料
Codeforces Round 919 (Div. 2) 题解:https://www.cnblogs.com/zsc985246/p/17963255
Editorial for Codeforces Round #919 (Div. 2):https://codeforces.com/blog/entry/122560
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17975392
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2023-01-19 D. Many Perfect Squares