rope大法好!
基本
是 $ ext $ 里面的一个 $ stl $ ,所以万能头重没有这个 $ stl $ ,要用新的头文件
$ rope $ 里面可以用 $ char $ , $ int $ , $ long long $ , $ double $ 。但是不能用 $ pair<int,int> $ !
#include<ext/rope>
using namespace __gnu_cxx
$ rope $ 的实现是可持久化平衡树,但是没有办法处理像可持久化数据结构模板题那种第 $ k $ 大数的问题
rope的函数
#include<ext/rope>
using namespace __gnu_cxx;
rope<int> h;
rope<int> w[N];
char c[N];
h.push_back(x); // 增加元素
h.insert(pos,s);
// 在pos这个位置插入x这个值,然后把原先的值都往后推
h.erase(pos,len);
// 从pos开始删去len个元素
h.size(); // 大小
h.replace(pos,x); // 替换
h.substr(pos,len);
// 从pos开始提出len个
h.copy(pos,len,c);
// 从pos开始提出len个复制到c中,这里的c不能是string!!
h[x]/h.at(x);
指针复制 $ O(1) $ ,数组复制 $ O(n) $ ,其它操作 $ O(logn) $
注意点
rope内部其实还是字符串,只不过我们习惯性的用int,所以用数组初始化的时候要注意一下
例题
核心代码
rope<int> *w[N];
w[0] = new rope<int>(-1);
for (int i = 1; i <= n; i ++) {
a = fr();
w[0]->push_back(a);
}
for (int i = 1; i <= m; i ++) {
if (type == 1) {
w[i] = new rope<int>(*w[k]);
w[i]->replace(loc,val);
} else {
w[i] = new rope<int>(*w[k]);
fw(w[i]->at(loc));
}
}
这个输入有亿点点阴间,核心代码
rope<char> w;
int pos = 0;
for (int i = 1; i <= T; i ++) {
cin >> type;
if (type == "Move") {
pos= k;
} else if (type == "Insert") {
int id = pos;
while (len) {
getline(cin,s);
for (int j = 0; j < s.length(); j ++) {
if ((int)s[j] >= 32 && (int)s[j] <= 126) {
w.insert(id,s[j]);
id ++,len --;
}
}
}
} else if (type == "Delete") {
w.erase(pos,len);
} else if (type == "Get") {
cout << w.substr(pos,len) << '\n';
} else if (type == "Prev") {
pos --;
} else pos ++;
这个题目和上面一题题意差不多,也就是多了一个有点阴间的翻转和很阴间的输入输出,谁家文本编辑器里面有换行符啊!!!谁还特判是不是换行符啊!!!$ CCF $ 请不要太自由了!!!
const int N = (1 << 22) + 5, inf = 0x3f3f3f3f;
char c[N],bc[N];
rope<char> w,h;
rope<char> tmp;
int T = fr();
string type,s;
int pos = 0;
for (int i = 1; i <= T; i ++) {
if (type == "Move") {
pos= k;
} else if (type == "Insert") {
int length = w.size();
for (int i = 0; i <len; i ++) {
c[i] = getchar();
bc[len - i - 1] = c[i];
}
c[len] = bc[len] = '\0';
w.insert(pos,c);
h.insert(length - pos,bc);
} else if (type == "Delete") {
int length = w.size();
w.erase(pos,len);
h.erase(length - pos - len,len);
} else if (type == "Rotate") {
int length = w.size();
tmp = w.substr(pos,len);
w = w.substr(0,pos) + h.substr(length - pos - len,len) + w.substr(pos + len,length - pos - len);
h = h.substr(0,length - pos - len) + tmp + h.substr(length - pos,pos);
} else if (type == "Get") {
putchar(w[pos]);
if (w[pos] != 10) puts("");
} else if (type == "Prev") {
pos --;
} else if (type == "Next") pos ++;
}
int n;
rope<int> w[N];
for (u = 1; u <= n; u ++) {
k = fr(),type = fr(), x = fr();
w[u] = w[k];
pos = lower_bound(w[u].begin(),w[u].end(),x) - w[u].begin();
if (type == 1) {
w[u].insert(pos,x);
} else if (type == 2) {
if (w[u][pos] != x) continue;
w[u].erase(pos,1);
} else if (type == 3) {
fw(pos + 1);
ch;
} else if (type == 4) {
fw(w[u][x - 1]);
ch;
} else if (type == 5) {
if (!pos) puts("-2147483647");
else fw(w[u][pos - 1]),ch;
} else {
pos = upper_bound(w[u].begin(),w[u].end(),x) - w[u].begin();
if (pos > w[u].size()) puts("2147486347");
else fw(w[u][pos]),ch;
}
}
P6182 Time Travel S
这里就注意一下他回到的是第\(x\)个操作之前
rope<int> w[N];
for (u = 1; u <= n; u ++) {
cin >> type;
if (type == 'a') {
w[u] = w[u - 1];
w[u].push_back(x);
} else if (type == 's') {
w[u] = w[u - 1];
w[u].pop_back();
} else {
w[u] = w[x - 1];
}
if (w[u].size() != 0)
fw(w[u][w[u].size() - 1]),ch;
else wj;
}
rope<char> w[N];
while (n --) {
if (s == "T") {
w[u] = w[u - 1];
w[u].push_back(c);
u ++;
} else if (s == "U") {
w[u] = w[u - x - 1];
u ++;
} else {
w[u] = w[u - 1];
putchar(w[u][x]),ch;
}
}
P3402 可持久化并查集
卡常失败了,有一个点死活卡不过去,罢了,九十五就九十五吧
rope<int> *h[N];
int f[N];
int find(int x) {
int t = h[u] -> at(x);
if (t != x)
return find(t);
return t;
}
for (int i = 1; i <= n; i ++)
f[i] = i;
f[0] = 1;
h[0] = new rope<int>(f);
for (u = 1; u <= m; u ++) {
if (type == 1) {
h[u] = new rope<int>(*h[u - 1]);
ha = find(a),hb = find(b);
if (ha == hb) continue;
h[u]->replace(ha,hb);
} else if (type == 2) {
h[u] = new rope<int>(*h[a]);
} else {
h[u] = new rope<int>(*h[u - 1]);
ha = find(a),hb = find(b);
if (ha == hb) puts("1");
else puts("0");
}
}

浙公网安备 33010602011771号