SYSU-6, Gym 100125L, splay
题目大意:每次往一个串里某个位置连续插n个字符a,或者删除一个区间,或者询问区间内有多少个字母(字母类型一共不超过26个),或者删除一段区间。
解:splay经典题,比较蛋疼的是删除,等价于把连续一段分裂成3(可以两个节点),我的写法很蠢,之后看了一下别人的代码如果维护一个找这个端点的上一个和下一个端点的函数能大幅减少创建节点的数量,这样写会快些,但是我手里积了很多其他题,也没时间改良了,日后有时间重写练手的时候改一下写法吧。
1 #include <cstdio> 2 #include <string> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <cstring> 7 #include <complex> 8 #include <set> 9 #include <vector> 10 #include <map> 11 #include <queue> 12 #include <deque> 13 #include <ctime> 14 15 using namespace std; 16 17 const double EPS = 1e-8; 18 19 #define ABS(x) ((x)<0?(-(x)):(x)) 20 #define SQR(x) ((x)*(x)) 21 #define MIN(a,b) ((a)<(b)?(a):(b)) 22 #define MAX(a,b) ((a)>(b)?(a):(b)) 23 24 #define LSON(x) ((x)<<1) 25 #define RSON(x) (((x)<<1)+1) 26 #define LOWBIT(x) ((x)&(-(x))) 27 #define MAXN 611111 28 #define VOIDPOINT 0 29 #define LL long long 30 #define OO 214748364 31 32 struct node{ 33 node *ch[2], *fath; 34 int size, tag, w, l; 35 inline int count() { 36 int res = 0; 37 for (int i = tag; i; i -= LOWBIT(i)) ++res; 38 return res; 39 } 40 inline void updata() { 41 size = l + (ch[0] ? ch[0]->size : 0) + (ch[1] ? ch[1]->size : 0); 42 tag = (ch[0] ? ch[0]->tag : 0) | (ch[1] ? ch[1]->tag : 0) | (1 << w); 43 } 44 inline void setCh(node *lson = VOIDPOINT, node *rson = VOIDPOINT) { 45 ch[0] = lson; if (lson) lson->fath = this; 46 ch[1] = rson; if (rson) rson->fath = this; 47 } 48 }; 49 50 struct SplayTree{ 51 node tree[MAXN], *root; 52 int cnt; 53 void clear() { 54 cnt = 0; 55 memset(tree, 0, sizeof(tree[0])); 56 } 57 node* newNode(int _w = 0, int _l = 0, node *father = VOIDPOINT) { 58 node *u = &tree[++cnt]; 59 60 u->ch[0] = u->ch[1] = VOIDPOINT; 61 u->w = _w; u->l = _l; 62 u->size = _l; u->tag = (1 << _w); 63 u->fath = father; 64 65 return u; 66 } 67 inline void rotate(node *now) { 68 node *p, *q; 69 p = now->fath; q = p->fath; 70 now->fath = q; p->fath = now; 71 if (p->ch[0] == now) { 72 if (p->ch[0] = now->ch[1]) p->ch[0]->fath = p; 73 now->ch[1] = p; 74 } else { 75 if (p->ch[1] = now->ch[0]) p->ch[1]->fath = p; 76 now->ch[0] = p; 77 } 78 if (q) { 79 if (q->ch[0] == p) q->ch[0] = now; 80 else q->ch[1] = now; 81 } 82 p->updata(); 83 } 84 inline void splay(node *now, node *goal = VOIDPOINT) { 85 node *p, *q; 86 while (now->fath != goal) { 87 p = now->fath; q = p->fath; 88 if (q == goal) { 89 rotate(now); break; 90 } 91 if ((now == p->ch[0] && p == q->ch[0]) || (now == p->ch[1] && p == q->ch[1])) { 92 rotate(p); rotate(now); 93 } else { 94 rotate(now); rotate(now); 95 } 96 } 97 now->updata(); 98 if (goal == VOIDPOINT) root = now; 99 } 100 node* insert(int pos, int val, int len) { 101 if (cnt == 0) { 102 root = newNode(val, len, VOIDPOINT); return root; 103 } 104 node *u = root; 105 for (;;) { 106 int tmp = (u->ch[0] ? u->ch[0]->size : 0); 107 if (pos <= tmp) { 108 if (u->ch[0] == VOIDPOINT) { 109 u->ch[0] = newNode(val, len, u); 110 splay(u->ch[0]); break; 111 } 112 u = u->ch[0]; 113 } else if (pos > tmp + u->l ) { 114 if (u->ch[1] == VOIDPOINT) { 115 u->ch[1] = newNode(val, len, u); 116 splay(u->ch[1]); break; 117 } 118 pos -= tmp + u->l; u = u->ch[1]; 119 } else { 120 pos -= tmp; 121 int lsz = pos - 1, rsz = u->l - pos + 1; 122 node *p, *q, *tt; 123 tt = newNode(val, len, u->fath); 124 125 if (u->fath) 126 u->fath->ch[ u->fath->ch[1] == u ] = tt; 127 128 p = lsz == 0 ? u->ch[0] : newNode(u->w, lsz, tt); 129 130 q = newNode(u->w, rsz, tt); q->setCh(VOIDPOINT, u->ch[1]); q->updata(); 131 132 if (lsz == 0) { 133 tt->setCh(u->ch[0], q); 134 } else { 135 p->setCh(u->ch[0], VOIDPOINT); p->updata(); 136 tt->setCh(p, q); 137 } 138 splay(tt); 139 break; 140 } 141 } 142 } 143 node* find(int pos) { 144 node *u = root; 145 for (;;) { 146 int tmp = u->ch[0] ? u->ch[0]->size : 0; 147 if (pos <= tmp) u = u->ch[0]; 148 else if (pos > tmp + u->l) { 149 pos -= tmp + u->l; 150 u = u->ch[1]; 151 } 152 else break; 153 } 154 return u; 155 } 156 void deletee(int l, int r) { 157 insert(l, 26, 1); insert(r+2, 26, 1); 158 node *t = find(r+3), *t2 = find(l-1); 159 splay(t2); 160 splay(find(r+3), t2); 161 t->ch[0] = VOIDPOINT; t->updata(); t->fath->updata(); 162 } 163 int query(int l, int r) { 164 insert(l, 26, 1); insert(r+2, 26, 1); 165 166 node *t = find(l), *t2 = find(r+2); 167 splay(t); 168 splay(t2, t); 169 170 int res = t2->ch[0]->count(); 171 172 deletee(r+2, r+2); deletee(l, l); 173 return res; 174 } 175 176 void dfs(node *u) const { 177 if (u->ch[0]) dfs(u->ch[0]); 178 179 for (int i = 0; i < u->l; ++i) putchar(u->w+'a'); 180 if (u->ch[1]) dfs(u->ch[1]); 181 } 182 void show() const { 183 node *u = root; 184 dfs(root); 185 cout << endl << "show end =========================== "<< root->size << endl; 186 } 187 } Tree; 188 189 int main() { 190 freopen("test.txt", "r", stdin); 191 // freopen("log.in", "r", stdin); 192 // freopen("log.out", "w", stdout); 193 194 Tree.clear(); 195 Tree.insert(1, 26, 1); 196 Tree.insert(1+1, 26, 1); 197 int n, pos, len, val; scanf("%d", &n); 198 char s[11]; 199 while (n--) { 200 // Tree.show(); 201 scanf("%s", s); 202 if (s[0] == '+') { 203 scanf("%d%d%s", &pos, &len, s); val = s[0] - 'a'; 204 Tree.insert(pos+1, val, len); 205 } else if (s[0] == '-') { 206 scanf("%d%d", &pos, &len); 207 Tree.deletee(pos+1, pos+1+len-1); 208 } else if (s[0] == '?') { 209 scanf("%d%d", &pos, &len); 210 printf("%d\n", Tree.query(pos+1, len+1)); 211 } else puts("Err"); 212 } 213 // Tree.show(); 214 fclose(stdin); 215 fclose(stdout); 216 return 0; 217 }