Shuffle Cards (STL rope平衡树库)
原创 已于 2024-05-16 17:44:13 修改 · 粉丝可见 · 1.1k 阅读 · 7 · 14 · 本内容遵循CC 4.0 BY-SA版权协议 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 GEO检测 · 编辑
文章链接:https://blog.csdn.net/hacker_51/article/details/138564364
本题链接: 登录—专业IT笔试面试备考平台_牛客网
题目:


样例1:
cobol<br/>5 1<br/>2 3<br/> |
样例2:
cobol<br/>5 2<br/>2 3<br/>2 3<br/> |
样例3:
cobol<br/>5 3<br/>2 3<br/>1 4<br/>2 4<br/> |
思路:
这道题,其实就是个模拟题,根据题意。
第一行输入,n 为排列数 1~n,初始为递增序列,m 为操作次数。
随后 m 行,第一个数是 下标pos,第二个数是 长度 len。
每次切割以下标 pos 做起点到长度len 的数组拿取出来,放到前面,,问操作后的最终序列。
根据这题意,尝试模拟一遍,截取长度数组方面,有一个办法是将它们当作string进行截取删除放置操作。
模拟代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| #include <iostream> #include <vector> #include <queue> #include <cstring> #include <algorithm> #include <unordered_map> #define endl '\n' #define int long long #define YES puts("YES") #define NO puts("NO") #define umap unordered_map #define All(x) x.begin(),x.end() #pragma GCC optimize(3,"Ofast","inline") #define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0) using namespace std; const int N = 2e6 + 10; inline void solve();
signed main() {
IOS; int _t = 1; while (_t--) { solve(); } return 0; } string s; int n,m;
inline void Init() { for(int i = 1;i <= n;++i) { s += char(i + '0'); } }
inline void Print_ans() { for(int i = 0;i < s.size();++i) { if(i) cout << ' '; cout << s[i]; } } inline void solve() { cin >> n >> m; Init(); while(m--) { int pos,len; cin >> pos >> len; pos -= 1; string tem = s.substr(pos,len); s.erase(pos,len); s = tem + s; } Print_ans(); }
|
提交后:

不出意料,超时了,这种明明是模拟题却出现超时的结果,这种情况就是需要一些特殊的数据结构了。
而这种结构之一,我们可以使用平衡树写法,平衡树的操作大部分都是 O(log n)时间复杂度,而我们上面的代码string的操作时间复杂度是 O(n),所以很容易出现超时的现象。
那么根据平衡树,手写的话会很麻烦,其实,C++STL库中也内置了平衡树的操作,我们可以调用。具体操作如下:
rope平衡树具体操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include<ext/rope> using namespace __gnu_cxx; rope <int> tree; int main(){ int x = 2; tree.push_back(x); tree.insert(pos, x); tree.erase(pos, len); tree.copy(pos, len, x); tree.replace(pos, x); tree.substr(pos, len); tree.at(i);tree[i]; return 0; }
|
并且rope< int>相当于一个块状链表。可以用substr等函数实现区间处理。
如果是rope< char>,相当于一个重型string。可以cout;可以+=。
rope最大的特点是支持可持久化。rope可以o(1)继承上一个版本。(内部维护了平衡树的指针)
最后要注意引用rope的细节:
1 2
| #include <ext/rope> using namespace __gnu_cxx;
|
代码详解如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| #include <iostream> #include <ext/rope> #define endl '\n' #define int long long #define All(x) x.begin(),x.end() #pragma GCC optimize(3,"Ofast","inline") #define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0) using namespace std; using namespace __gnu_cxx; const int N = 2e6 + 10; inline void solve();
signed main() {
IOS; int _t = 1; while (_t--) { solve(); } return 0; }
int n,m; rope<int>tree;
inline void Init() { for(int i = 1;i <= n;++i) tree.push_back(i); }
inline void Print_ans() { for(int i = 0;i < (int)tree.size();++i) { if(i) cout << ' '; cout << tree[i]; } } inline void solve() { cin >> n >> m; Init(); while(m--) { int pos,len; cin >> pos >> len; pos -= 1; rope<int> tem = tree.substr(pos,len); tree.erase(pos,len); tree = tem + tree; } Print_ans(); }
|
最后提交:
