UVALive 6145 Version Controlled IDE(可持久化treap、rope)

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4156

题目拷贝难度大我就不复制了。

题目大意:维护一个字符串,要求支持插入、删除操作,还有输出第 i 次操作后的某个子串。强制在线。

思路1:使用可持久化treap可破,详细可见CLJ的《可持久化数据结构的研究》。

思路2:rope大法好,详见:http://blog.csdn.net/guognib/article/details/20563453(文档:http://www.sgi.com/tech/stl/Rope.html),代码短速度快,可惜不能打lazy标记。

PS:自从学了函数式编程,发现可持久化什么的都变简单了。

PS:不用智能指针只要845MS。这真是一个大坑。本来我换成普通指针只是想用于调试……

PS:UVALive居然不保存代码!于是我又去vjudge交了一次。

代码(C++11 2116MS):

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3
  4 struct Node;
  5 typedef shared_ptr<Node> Nptr;
  6 //typedef Node* Nptr;
  7
  8 struct Node {
  9     Nptr lson, rson;
 10     int size, weight;
 11     char c;
 12     void update() {
 13         size = lson->size + rson->size + 1;
 14     }
 15 };
 16 Nptr nil;
 17
 18 Nptr new_node(char c) {
 19     Nptr x = Nptr(new Node);
 20     x->lson = x->rson = nil;
 21     x->size = 1;
 22     x->weight = rand();
 23     x->c = c;
 24     return x;
 25 }
 26
 27 Nptr new_node(char c, Nptr lson, Nptr rson) {
 28     Nptr x = Nptr(new Node);
 29     x->lson = lson;
 30     x->rson = rson;
 31     x->update();
 32     x->weight = rand();
 33     x->c = c;
 34     return x;
 35 }
 36
 37 void initTreap() {
 38     nil = Nptr(new Node);
 39     nil->lson = nil->rson = nil;
 40     nil->size = 0;
 41 }
 42
 43 Nptr build(char *st, char *ed) {
 44     if(st == ed) return nil;
 45     assert(st < ed);
 46     char *mid = st + (ed - st) / 2;
 47     return new_node(*mid, build(st, mid), build(mid + 1, ed));
 48 }
 49
 50 typedef pair<Nptr, Nptr> Ppp;
 51
 52 Ppp split(Nptr x, int n) {
 53     if(n == 0) return make_pair(nil, x);
 54     int ls = x->lson->size;
 55
 56     if(ls >= n) {
 57         Ppp a = split(x->lson, n);
 58         return make_pair(a.first, new_node(x->c, a.second, x->rson));
 59     } else {
 60         Ppp a = split(x->rson, n - ls - 1);
 61         return make_pair(new_node(x->c, x->lson, a.first), a.second);
 62     }
 63 }
 64
 65 Nptr merge(Nptr a, Nptr b) {
 66     if(a == nil) return b;
 67     if(b == nil) return a;
 68     if(a->weight < b->weight) {
 69         return new_node(a->c, a->lson, merge(a->rson, b));
 70     } else {
 71         return new_node(b->c, merge(a, b->lson), b->rson);
 72     }
 73 }
 74
 75 int print(Nptr x) {
 76     if(x == nil) return 0;
 77     int res = (x->c == ‘c‘);
 78     res += print(x->lson);
 79     putchar(x->c);
 80     res += print(x->rson);
 81     return res;
 82 }
 83
 84 Nptr insert(Nptr x, int pos, char s[]) {
 85     Nptr a = build(s, s + strlen(s));
 86     Ppp p = split(x, pos);
 87     return merge(p.first, merge(a, p.second));
 88 }
 89
 90 Nptr remove(Nptr x, int pos, int len) {
 91     Ppp a = split(x, pos);
 92     Ppp b = split(a.second, len);
 93     return merge(a.first, b.second);
 94 }
 95
 96 int print(Nptr x, int pos, int len) {
 97     Ppp a = split(x, pos);
 98     Ppp b = split(a.second, len);
 99     int res = print(b.first);
100     puts("");
101     return res;
102 }
103
104 Nptr rt[50010];
105 char s[110];
106 int n, d, vnow;
107
108 int main() {
109     initTreap();
110     rt[0] = nil;
111
112     scanf("%d", &n);
113     while(n--) {
114         int v, p, c, op;
115         scanf("%d", &op);
116         if(op == 1) {
117             scanf("%d%s", &p, s);
118             p -= d;
119             vnow++;
120             rt[vnow] = insert(rt[vnow - 1], p, s);
121         }
122         if(op == 2) {
123             scanf("%d%d", &p, &c);
124             p -= d, c -= d;
125             vnow++;
126             rt[vnow] = remove(rt[vnow - 1], p - 1, c);
127         }
128         if(op == 3) {
129             scanf("%d%d%d", &v, &p, &c);
130             v -= d, p -= d, c -= d;
131             d += print(rt[v], p - 1, c);
132         }
133     }
134 }

代码(rope大法 322MS):

 1 #include <bits/stdc++.h>
 2 #include <ext/rope>
 3 using namespace std;
 4 #define FOR(i, n) for(int i = 0; i < n; ++i)
 5
 6 const int MAXN = 50010;
 7 const int MAXS = 200010;
 8
 9 __gnu_cxx::crope rt[MAXN], tmp;
10
11 char s[MAXS];
12 int m, vnow, d;
13
14 int main() {
15     scanf("%d", &m);
16     while(m--) {
17         int op, p, v, c;
18         scanf("%d", &op);
19         if(op == 1) {
20             scanf("%d%s", &p, s);
21             p -= d;
22             rt[vnow + 1] = rt[vnow];
23             rt[++vnow].insert(p, s);
24         } else if(op == 2) {
25             scanf("%d%d", &p, &c);
26             p -= d, c -= d;
27             rt[vnow + 1] = rt[vnow];
28             rt[++vnow].erase(p - 1, c);
29         } else if(op == 3) {
30             scanf("%d%d%d", &v, &p, &c);
31             v -= d, p -= d, c -= d;
32             tmp = rt[v].substr(p - 1, c);
33             printf("%s\n", tmp.c_str());
34             d += count(tmp.begin(), tmp.end(), ‘c‘);
35         }
36     }
37 }

时间: 2024-12-20 18:00:00

UVALive 6145 Version Controlled IDE(可持久化treap、rope)的相关文章

UVA12538 - Version Controlled IDE

https://uva.onlinejudge.org/index.php 可持久化fhp-treap.像线段树的可持久化一样自上至下,每次新建log(n)个节点即可. #include<bits/stdc++.h> const int maxn=50015,maxlen=115; using namespace std; int n,cnt; struct Ttreap{ int tot,ver; static const int maxnode=10000015; struct Tnode

好久不见的博客咯!——没有可持久化的可持久化treap

每每想要去了解可持久化treap这个好写好调的东东,然后就发现网上只有一个人的--SymenYang的!在此我必须得把他批判一番--写方法不贴代码是什么心态!而且写出来的是有问题的呀!害人不浅! 好吧说正经事,这个版本的treap名叫可持久化treap却没有可持久化,而是借鉴了可持久化treap中的一些写法.貌似可持久化之后反而难写难调...在这个版本的treap中加入了堆权值来维护树的形状,然后由三种操作--合并(merge),按size拆分(split_size),按值拆分(split_kt

脑洞大开加偏执人格——可持久化treap版的Link Cut Tree2

试了一下先上再下的Treap方式,很高兴,代码变短了,但是,跑的变慢了!!!其实慢得不多,5%左右.而且这个版本的写法不容易写错..只要会一般可持久化Treap的人写着都不难...就是相对于(压行的)Splay还是长了点... 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <algorithm> 5 6 using namespace std; 7

BZOJ 3595: [Scoi2014]方伯伯的Oj SBT+可持久化Treap

3595: [Scoi2014]方伯伯的OjTime Limit: 6 Sec  Memory Limit: 256 MBSubmit: 102  Solved: 54[Submit][Status] Description 方伯伯正在做他的Oj.现在他在处理Oj上的用户排名问题. Oj上注册了n个用户,编号为1-",一开始他们按照编号排名.方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和编号: 1.操作格式为1 x y,意味着将编号为z的用户编号改为V,而排名不变,执行完该操作后需要

脑洞大开加偏执人格——可持久化treap版的Link Cut Tree

一直没有点动态树这个科技树,因为听说只能用Splay,用Treap的话多一个log.有一天脑洞大开,想到也许Treap也能从底向上Split.仔细思考了一下,发现翻转标记不好写,再仔细思考了一下,发现还是可以写的,只需要实时交换答案二元组里的两棵树,最后在吧提出来的访问节点放回去就行了.本着只学一种平衡树的想法,脑洞大开加偏执人格的开始写可持久化Treap版的Link Cut Tree... 写了才发现,常数硕大啊!!!代码超长啊!!!因为merge是从上到下,split从下到上,pushdow

[rope大法好] STL里面的可持久化平衡树--rope

简单用法: #include <ext/rope> using namespace __gnu_cxx; int a[1000]; rope<int> x; rope<int> x(a,a + n); rope<int> a(x); x->at(10); x[10]; x->push_back(x) // 在末尾添加x x->insert(pos,x) // 在pos插入x x->erase(pos,x) // 从pos开始删除x个

可持久化Treap(fhq Treap,非旋转式Treap)学习(未完待续)

简介: Treap,一种表现优异的BST 优势: 其较于AVL.红黑树实现简单,浅显易懂 较于Splay常数小,通常用于树套BST表现远远优于Splay 或许有人想说SBT,SBT我没有实现过,据说比较快 但是SBT.Splay以及旋转版Treap等BST都不可以比较方便地实现‘可持久化操作 Treap=Tree+Heap Treap是一颗同时拥有二叉搜索树和堆性质的一颗二叉树 Treap有两个关键字,在这里定义为: 1.key,满足二叉搜索树性质,即中序遍历按照key值有序 2.fix,满足堆

uvalive 5031 Graph and Queries 名次树+Treap

题意:给你个点m条边的无向图,每个节点都有一个整数权值.你的任务是执行一系列操作.操作分为3种... 思路:本题一点要逆向来做,正向每次如果删边,复杂度太高.逆向到一定顺序的时候添加一条边更容易.详见算法指南P235. 1 #include<cstdlib> 2 3 struct Node 4 { 5 Node *ch[2]; // 左右子树 6 int r; // 随机优先级 7 int v; // 值 8 int s; // 结点总数 9 Node(int v):v(v) 10 { 11

【模板】可持久化Treap

洛谷3835 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstdlib> 4 #define ls (a[u].l) 5 #define rs (a[u].r) 6 #define R (root[Ver]) 7 #define update(u) (a[u].size=a[a[u].l].size+a[a[u].r].size+1) 8 #define copy(x) (a[++tot]=a[x],a[x=