有关论文:
splay的伸展操作 splay(x,goal)将x节点移到goal节点的下方,通过左旋和右旋基本操作实现,其实现过程在论文中有详细介绍。
对于用splay去维护一个数列,有以下常用操作。
1.splay(x,goal) 将结点k旋转到goal结点的下方
2.getpos(x) 查询第x个节点的在树中的位置。
3.rotateto(x,goal) 将第x个结点旋转到goal结点下方,可以由 rotateto(x,goal) = splay(getpos(x),goal)得到
4.插入操作,在L,R之间插入一个区间或者一个数,先rotateto(L-1,0),然后rotateto(R+1,root),把L-1旋转到根结点,把R+1旋转到根节点的右儿子结点上,然后插入的东西插入在根的右儿子的左儿子结点上,这样就保证插入的数据夹在L,R之间,为了防止L-1,R-1越界,可以添加两个无用结点。
5.删除操作,同上。
6.翻转操作,将区间[L,R]翻转,可以先和插入操作进行同样的处理,先把L,R 区间 夹在 L-1和R+1结点之间,然后对关键节点打上翻转标记(懒惰标记),类似线段树。
下面贴上HH的splay模板:
/* http://acm.pku.edu.cn/JudgeOnline/problem?id=3468 区间跟新,区间求和 */ #include <cstdio> #define keyTree (ch[ ch[root][1] ][0]) const int maxn = 222222; struct SplayTree{ int sz[maxn]; int ch[maxn][2]; int pre[maxn]; int root , top1 , top2; int ss[maxn] , que[maxn]; inline void Rotate(int x,int f) { int y = pre[x]; push_down(y); push_down(x); ch[y][!f] = ch[x][f]; pre[ ch[x][f] ] = y; pre[x] = pre[y]; if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] = x; ch[x][f] = y; pre[y] = x; push_up(y); } inline void Splay(int x,int goal) { push_down(x); while(pre[x] != goal) { if(pre[pre[x]] == goal) { Rotate(x , ch[pre[x]][0] == x); } else { int y = pre[x] , z = pre[y]; int f = (ch[z][0] == y); if(ch[y][f] == x) { Rotate(x , !f) , Rotate(x , f); } else { Rotate(y , f) , Rotate(x , f); } } } push_up(x); if(goal == 0) root = x; } inline void RotateTo(int k,int goal) {//把第k位的数转到goal下边 int x = root; push_down(x); while(sz[ ch[x][0] ] != k) { if(k < sz[ ch[x][0] ]) { x = ch[x][0]; } else { k -= (sz[ ch[x][0] ] + 1); x = ch[x][1]; } push_down(x); } Splay(x,goal); } inline void erase(int x) {//把以x为祖先结点删掉放进内存池,回收内存 int father = pre[x]; int head = 0 , tail = 0; for (que[tail++] = x ; head < tail ; head ++) { ss[top2 ++] = que[head]; if(ch[ que[head] ][0]) que[tail++] = ch[ que[head] ][0]; if(ch[ que[head] ][1]) que[tail++] = ch[ que[head] ][1]; } ch[ father ][ ch[father][1] == x ] = 0; pushup(father); } //以上一般不修改////////////////////////////////////////////////////////////////////////////// void debug() {printf("%d\n",root);Treaval(root);} void Treaval(int x) { if(x) { Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]); Treaval(ch[x][1]); } } //以上Debug //以下是题目的特定函数: inline void NewNode(int &x,int c) { if (top2) x = ss[--top2];//用栈手动压的内存池 else x = ++top1; ch[x][0] = ch[x][1] = pre[x] = 0; sz[x] = 1; val[x] = sum[x] = c;/*这是题目特定函数*/ add[x] = 0; } //把延迟标记推到孩子 inline void push_down(int x) {/*这是题目特定函数*/ if(add[x]) { val[x] += add[x]; add[ ch[x][0] ] += add[x]; add[ ch[x][1] ] += add[x]; sum[ ch[x][0] ] += (long long)sz[ ch[x][0] ] * add[x]; sum[ ch[x][1] ] += (long long)sz[ ch[x][1] ] * add[x]; add[x] = 0; } } //把孩子状态更新上来 inline void push_up(int x) { sz[x] = 1 + sz[ ch[x][0] ] + sz[ ch[x][1] ]; /*这是题目特定函数*/ sum[x] = add[x] + val[x] + sum[ ch[x][0] ] + sum[ ch[x][1] ]; } /*初始化*/ inline void makeTree(int &x,int l,int r,int f) { if(l > r) return ; int m = (l + r)>>1; NewNode(x , num[m]); /*num[m]权值改成题目所需的*/ makeTree(ch[x][0] , l , m - 1 , x); makeTree(ch[x][1] , m + 1 , r , x); pre[x] = f; push_up(x); } inline void init(int n) {/*这是题目特定函数*/ ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0; add[0] = sum[0] = 0; root = top1 = 0; //为了方便处理边界,加两个边界顶点 NewNode(root , -1); NewNode(ch[root][1] , -1); pre[top1] = root; sz[root] = 2; for (int i = 0 ; i < n ; i ++) scanf("%d",&num[i]); makeTree(keyTree , 0 , n-1 , ch[root][1]); push_up(ch[root][1]); push_up(root); } /*更新*/ inline void update( ) {/*这是题目特定函数*/ int l , r , c; scanf("%d%d%d",&l,&r,&c); RotateTo(l-1,0); RotateTo(r+1,root); add[ keyTree ] += c; sum[ keyTree ] += (long long)c * sz[ keyTree ]; } /*询问*/ inline void query() {/*这是题目特定函数*/ int l , r; scanf("%d%d",&l,&r); RotateTo(l-1 , 0); RotateTo(r+1 , root); printf("%lld\n",sum[keyTree]); } /*这是题目特定变量*/ int num[maxn]; int val[maxn]; int add[maxn]; long long sum[maxn]; }spt; int main() { int n , m; scanf("%d%d",&n,&m); spt.init(n); while(m --) { char op[2]; scanf("%s",op); if(op[0] == ‘Q‘) { spt.query(); } else { spt.update(); } } return 0; }
NOI2005维修序列,囊括的splay的基本操作,要使用内存池回收内存
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<iostream> #include<string.h> #include<queue> #include<stack> #include<list> #include<stdlib.h> #include<algorithm> #include<vector> #include<map> #include<cstring> #include<set> #include <fstream> using namespace std; #define keytree ch[ ch[root][1]][0] const int maxn = 500005 + 20; int ch[maxn][2], Size[maxn]; int pre[maxn], val[maxn], sum[maxn], lsum[maxn], rsum[maxn], Max[maxn], colorall[maxn], colorrev[maxn], a1[maxn]; int que[maxn]; int top2; int ss[maxn]; int tot, root; int pos; const int INF = -1e9; void update_same(int r, int v) { if (!r) return; colorall[r] = 1; val[r] = v; sum[r] = Size[r] * v; lsum[r] = rsum[r] = Max[r] = max(v, sum[r]); } void update_rev(int r) { if (!r) return; swap(ch[r][0], ch[r][1]); swap(lsum[r], rsum[r]); colorrev[r] ^= 1; } void newnode(int &x, int fa, int key) { //x = ++tot; if (top2) x = ss[top2--]; else x = ++tot; pre[x] = fa; Size[x] = 1; val[x] = key; sum[x] = key; lsum[x] = rsum[x] = Max[x] = key; ch[x][0] = ch[x][1] = 0; colorrev[x] = 0; colorall[x] = 0; } void up(int x) { int l = ch[x][0]; int r = ch[x][1]; Size[x] = Size[l] + Size[r] + 1; sum[x] = sum[l] + sum[r] + val[x]; lsum[x] = max(lsum[l], sum[l] + val[x] + max(0, lsum[r])); rsum[x] = max(rsum[r], sum[r] + val[x] + max(0, rsum[l])); Max[x] = max(0, rsum[l]) + val[x] + max(0, lsum[r]); Max[x] = max(Max[l], max(Max[r], Max[x])); } void down(int r) { if (colorrev[r]) { update_rev(ch[r][0]); update_rev(ch[r][1]); colorrev[r] = 0; } if (colorall[r]) { update_same(ch[r][0], val[r]); update_same(ch[r][1], val[r]); colorall[r] = 0; } } void build(int &x, int fa, int l, int r) { if (l > r) return; int mid = (l + r) >> 1; newnode(x, fa, a1[mid]); build(ch[x][0], x, l, mid - 1); build(ch[x][1], x, mid + 1, r); up(x); } void init(int n) { tot = top2 = root = 0; Size[0] = colorrev[0] = pre[0] = ch[0][0] = ch[0][1] = val[0] = sum[0] = colorall[0] = 0; lsum[0] = rsum[0] = Max[0] = INF; newnode(root, 0, -1); newnode(ch[root][1], root, -1); // up(root); for (int i = 0; i < n; i++) { scanf("%d", &a1[i]); } build(keytree, ch[root][1], 0, n - 1); //傻逼了 ch[root][1] 变成root了 // up(ch[root][1]); up(root); } void rotate(int x, int kind) { int y = pre[x]; down(y); down(x); ch[y][!kind] = ch[x][kind]; pre[ch[x][kind]] = y; if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x; ch[x][kind] = y; pre[x] = pre[y]; pre[y] = x; up(y); } inline void splay(int x, int goal) { down(x); while (pre[x] != goal) { if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x); else { int y = pre[x]; int z = pre[y]; //down(z); down(y); down(x); //先down z 减少 rotateto 里面的 down y ,x 次数 int kind = ch[z][0] == y; if (ch[y][kind] == x) { rotate(x, !kind); rotate(x, kind); } else { rotate(y, kind); rotate(x, kind); } } } up(x); if (goal == 0) root = x; } int getpos(int k) { int r = root; down(r); while (Size[ch[r][0]] != k) { if (k < Size[ch[r][0]]) r = ch[r][0]; else { k -= Size[ch[r][0]] + 1; r = ch[r][1]; } down(r); } return r; } void erase(int x) { if (!x) return; ss[++top2] = x; erase(ch[x][0]); erase(ch[x][1]); } void rotateto(int x, int y) { int t = getpos(x); splay(t, y); } void Delete(int pos, int k) { int ll = pos - 1; int rr = pos + k; rotateto(ll, 0); rotateto(rr, root); erase(keytree); pre[keytree] = 0; keytree = 0; //up(ch[root][1]); //up(root); } void insert(int pos, int k) { rotateto(pos, 0); rotateto(pos + 1, root); //这样插会变快 for (int i = 0; i < k; i++) scanf("%d", &a1[i]); build(keytree, ch[root][1], 0, k-1); //up(ch[root][1]); //up(root); } void updateall(int pos, int k, int c) { int ll = pos - 1; int rr = pos + k; rotateto(ll, 0); rotateto(rr, root); update_same(keytree, c); //up(ch[root][1]); //up(root); } void rev(int pos, int k) { int ll = pos - 1; int rr = pos + k; rotateto(ll, 0); rotateto(rr, root); update_rev(keytree); } void asksum(int pos, int k) { int ll = pos - 1; int rr = pos + k; rotateto(ll, 0); rotateto(rr, root); printf("%d\n", sum[keytree]); } void askmax() { splay(1, 0); splay(2, root); printf("%d\n", Max[keytree]); } int main() { int n, m, a, b, c; char str[20]; while (scanf("%d%d", &n, &m) != EOF) { init(n); while (m--) { scanf("%s", str); if (str[0] == ‘M‘&&str[2] == ‘X‘) { askmax(); continue; } if (str[0] == ‘I‘) { scanf("%d%d", &a, &b); insert(a, b); } if (str[0] == ‘D‘) { scanf("%d%d", &a, &b); Delete(a, b); } if (str[0] == ‘M‘) { scanf("%d%d%d", &a, &b, &c); updateall(a, b, c); } if (str[0] == ‘R‘) { scanf("%d%d", &a, &b); rev(a, b); } if (str[0] == ‘G‘) { scanf("%d%d", &a, &b); asksum(a, b); } } } return 0; }
HDU4453 Looploop 12年杭州
一些splay的常用操作,注意循环取余和结点翻转后更新指针位置,注释中有
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<iostream> #include<string> #include<queue> #include<stack> #include<list> #include<stdlib.h> #include<algorithm> #include<vector> #include<map> #include<cstring> #include<set> #include <fstream> using namespace std; typedef long long LL; #define keytree ch[ ch[root][1]][0] inline bool scanf_(int &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; //EOF while (c != ‘-‘ && (c<‘0‘ || c>‘9‘)) c = getchar(); sgn = (c == ‘-‘) ? -1 : 1; ret = (c == ‘-‘) ? 0 : (c - ‘0‘); while (c = getchar(), c >= ‘0‘&&c <= ‘9‘) ret = ret * 10 + (c - ‘0‘); ret *= sgn; return 1; } inline void printf_(int x) { if (x>9) printf_(x / 10); putchar(x % 10 + ‘0‘); } const int maxn = 5e5 + 20; int tot, root; int pre[maxn], coloradd[maxn], colorrev[maxn], Size[maxn], val[maxn], ch[maxn][2]; int pos, n; int a[maxn]; void newnode(int &x, int fa, int key) { x = ++tot; pre[x] = fa; val[x] = key; Size[x] = 1; ch[x][0] = ch[x][1] = 0; coloradd[x] = 0; colorrev[x] = 0; } void downadd(int rt, int add) { if (rt == 0) return; val[rt] += add; coloradd[rt] += add; } void downrev(int rt) { if (rt == 0) return; swap(ch[rt][0], ch[rt][1]); int ll = ch[rt][0]; int rr = ch[rt][1]; colorrev[rt] ^= 1; } void up(int rt) { int ll = ch[rt][0]; int rr = ch[rt][1]; Size[rt] = Size[ll] + Size[rr] + 1; } void down(int rt) { int ll = ch[rt][0]; int rr = ch[rt][1]; if (colorrev[rt]) { downrev(ll); downrev(rr); colorrev[rt] = 0; } if (coloradd[rt]) { downadd(ll, coloradd[rt]); downadd(rr, coloradd[rt]); coloradd[rt] = 0; } } void Treaval(int x) { if (x) { down(x); Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %d val = %d \n", x, ch[x][0], ch[x][1], pre[x], Size[x], val[x]); Treaval(ch[x][1]); } } void debug() { //printf("%d\n", root); Treaval(root); } void build(int &x, int l, int r, int fa) { if (l > r) return; int mid = (l + r) >> 1; newnode(x, fa, a[mid]); build(ch[x][0], l, mid - 1, x); build(ch[x][1], mid + 1, r, x); up(x); } void rotate(int x, int kind) { int y = pre[x]; down(y); down(x); ch[y][!kind] = ch[x][kind]; pre[ch[x][kind]] = y; if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x; ch[x][kind] = y; pre[x] = pre[y]; pre[y] = x; up(y); } inline void splay(int x, int goal) { down(x); while (pre[x] != goal) { if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x); else { int y = pre[x]; int z = pre[y]; down(z); down(y); down(x); //先down z 减少 rotateto 里面的 down y ,x 次数 int kind = ch[z][0] == y; if (ch[y][kind] == x) { rotate(x, !kind); rotate(x, kind); } else { rotate(y, kind); rotate(x, kind); } } } up(x); if (goal == 0) root = x; } int getpos(int k) { int r = root; down(r); while (Size[ch[r][0]] != k) { if (k < Size[ch[r][0]]) r = ch[r][0]; else { k -= Size[ch[r][0]] + 1; r = ch[r][1]; } down(r); } return r; } void rotateto(int x, int goal) { int t = getpos(x); splay(t, goal); } void gaoadd(int L, int R, int add) { rotateto(L - 1, 0); rotateto(R + 1, root); downadd(keytree, add); } void gaoreverse(int L, int R) { rotateto(L - 1, 0); rotateto(R + 1, root); downrev(keytree); } void gaoinsert(int x) { rotateto(pos, 0); rotateto(pos + 1, root); newnode(keytree, ch[root][1], x); } void gaodelete() { rotateto(pos - 1, 0); rotateto(pos + 1, root); keytree = 0; } void ask() { rotateto(pos - 1, 0); rotateto(pos + 1, root); printf_(val[keytree]); putchar(‘\n‘); } void init() { root = tot = 0; ch[0][1] = ch[0][0] = Size[0] = val[0] = coloradd[0] = colorrev[0] = pre[0] = 0; newnode(root, 0, -1); newnode(ch[root][1], root, -1); build(keytree, 0, n - 1, ch[root][1]); } void gaoreverse1(int L, int R, int L1, int R1)//跨越两端的区间翻转,先将两边的翻转,然后交换位置 { rotateto(L - 1, 0); rotateto(R + 1, root); int t = keytree; int t1 = ch[root][1]; int t2 = root; downrev(keytree); keytree = 0; rotateto(L1 - 1, 0); rotateto(R1 + 1, root); int t3 = keytree; downrev(keytree); keytree = t; pre[t] = ch[root][1]; splay(t2, 0); splay(t1, root); keytree = t3; pre[t3] = ch[root][1]; splay(keytree, 0); } int main() { int k1, k2, m, x; char str[10]; int Icase = 0; while (scanf_(n)) { scanf_(m); scanf_(k1); scanf_(k2); if (n == 0 && m == 0 && k1 == 0 && k2 == 0) break; printf("Case #%d:\n", ++Icase); for (int i = 0; i < n; i++) { scanf_(a[i]); } init(); pos = 1; while (m--) { scanf("%s", str); if (str[0] == ‘a‘) { scanf_(x); int t = pos + k2 - 1; if (t <= n) { gaoadd(pos, t, x); } else { gaoadd(pos, n, x); t %= n; gaoadd(1, t, x); } } if (str[0] == ‘r‘) { int t = pos + k1 - 1; if (t <= n) { gaoreverse(pos, t); } else { gaoreverse1(pos, n, 1, t%n); pos = (n + 1) - (t%n); // 结点翻转交换以后,pos的位置更新 } } if (str[0] == ‘i‘) { scanf_(x); gaoinsert(x); n++; } if (str[0] == ‘d‘) { gaodelete(); n--; if (pos > n) pos = 1; } if (str[0] == ‘m‘) { scanf_(x); if (x == 1) { pos--; if (pos == 0) pos = n; } if (x == 2) { pos++; if (pos == n + 1) pos = 1; } } if (str[0] == ‘q‘) { ask(); } } } return 0; }
HDU4441Queue Sequence 12年天津
有个插入操作,在它插入的位置后面离他最近的正数所对应的负数前面插入它的负数。
怎么搞呢?别人教我的,每个节点再维护一个价值,如果这个结点是负数则这个结点的价值是1,然后在维护区间和,这样就可以通过左子树的区间和大小,从根向下查到离他最近的价值为1的位置。
还有一个要注意的小点,由于每个正数只出现一次,在建立结点的时候就可以记录这个数字所对应的结点,然后注意点细节,调就好了。
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<iostream> #include<string.h> #include<queue> #include<stack> #include<list> #include<stdlib.h> #include<algorithm> #include<vector> #include<map> #include<cstring> #include<set> #include <fstream> using namespace std; #define keytree ch[ ch[root][1]][0] const int maxn = 4e5 + 20; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 const int INF = 1e9; int sum1[maxn << 2]; void build(int l, int r, int rt) { sum1[rt] = 0; if (l == r) return; int mid = (l + r) >> 1; build(lson); build(rson); } void up1(int rt) { sum1[rt] = sum1[rt << 1] + sum1[rt << 1 | 1]; } void update(int key, int l, int r, int rt) { if (l == r) { sum1[rt] ^= 1; return; } int mid = (l + r) >> 1; if (key <= mid) update(key, lson); else update(key, rson); up1(rt); } int ask(int l, int r, int rt) { if (l == r) return l; int mid = (l + r) >> 1; int len = mid - l + 1; if (sum1[rt << 1] == len) return ask(rson); else return ask(lson); } int tot, root, pre[maxn], ch[maxn][2], Size[maxn], pos[maxn], LL[maxn], val[maxn], oppo[maxn], n; int suml[maxn]; long long sum[maxn]; void Treaval(int x) { if (x) { Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %d val = %d suml = %d\n", x, ch[x][0], ch[x][1], pre[x], Size[x], val[x],suml[x]); Treaval(ch[x][1]); } } void debug() { printf("%d\n", root); Treaval(root); } void newnode(int &x, int fa, int key) { x = ++tot; pre[x] = fa; Size[x] = 1; ch[x][0] = ch[x][1] = 0; val[x] = key; sum[x] = key; if (key > 0) pos[key] = x; if (key > 0) LL[x] = 1, suml[x] = 1; else LL[x] = 0, suml[x] = 0; } void up(int x) { int ll = ch[x][0]; int rr = ch[x][1]; Size[x] = Size[ll] + Size[rr] + 1; sum[x] = sum[ll] + sum[rr] + val[x]; suml[x] = suml[ll] + suml[rr] + LL[x]; } void rotate(int x, int kind) { int y = pre[x]; ch[y][!kind] = ch[x][kind]; pre[ch[x][kind]] = y; if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x; ch[x][kind] = y; pre[x] = pre[y]; pre[y] = x; up(y); } inline void splay(int x, int goal) { while (pre[x] != goal) { if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x); else { int y = pre[x]; int z = pre[y]; //down(z); down(y); down(x); //先down z 减少 rotateto 里面的 down y ,x 次数 int kind = ch[z][0] == y; if (ch[y][kind] == x) { rotate(x, !kind); rotate(x, kind); } else { rotate(y, kind); rotate(x, kind); } } } up(x); if (goal == 0) root = x; } int getpos(int k) { int r = root; while (Size[ch[r][0]] != k) { if (k < Size[ch[r][0]]) r = ch[r][0]; else { k -= Size[ch[r][0]] + 1; r = ch[r][1]; } } return r; } void rotateto(int x, int goal) { int t = getpos(x); splay(t, goal); } int getpre(int i) { splay(i, 0); int r = root; r = ch[root][0]; while (ch[r][1]) { r = ch[r][1]; } return r; } int getlast(int i) { splay(i, 0); int r = root; r = ch[root][1]; while (ch[r][0]) r = ch[r][0]; return r; } int asklast(int r) { //printf("%d %d %d asdf\n",r,ch[r][1], suml[ch[r][1]]); int ll = ch[r][0]; int rr = ch[r][1]; if (ch[r][1] == 0) return -1; if (suml[rr] == 0) return -1; r = ch[r][1]; while (r) { ll = ch[r][0]; rr = ch[r][1]; if (suml[ll] == 0 && LL[r]) break; if (suml[ll]) r = ch[r][0]; else r = ch[r][1]; } return r; } void insert(int p) { int t = ask(1, n, 1); rotateto(p, 0); rotateto(p + 1, root); newnode(keytree, ch[root][1], t); splay(keytree, 0); update(t, 1, n, 1); int t1 = asklast(root); if (t1 == -1) { int ll = getpre(2); splay(ll, 0); splay(2, root); newnode(keytree, ch[root][1], -t); oppo[t] = keytree; } else { int ll = getpre(oppo[val[t1]]); splay(ll, 0); splay(oppo[val[t1]], root); newnode(keytree, ch[root][1], -t); oppo[t] = keytree; } } void remove(int i) { int ll = getpre(pos[i]); int rr = getlast(pos[i]); splay(ll, 0); splay(rr, root); ch[ch[root][1]][0] = 0; ll = getpre(oppo[i]); rr = getlast(oppo[i]); splay(ll, 0); splay(rr, root); ch[ch[root][1]][0] = 0; update(i, 1, n, 1); } void ask(int i) { int ll = pos[i]; int rr = oppo[i]; //debug(); ll = getpre(ll); rr = getlast(rr); splay(ll, 0); splay(rr, root); printf("%I64d\n", sum[keytree]); } void init() { build(1, n, 1); root = tot = Size[0] = pos[0] = oppo[0] = suml[0] = LL[0] = 0; sum[0] = 0; newnode(root, 0, 0); newnode(ch[root][1], root, 0); } int main() { int a; char str[10]; int Icase = 0; while (scanf("%d", &n) != EOF) { printf("Case #%d:\n", ++Icase); init(); for (int i = 0; i < n; i++) { scanf("%s%d", str, &a); if (str[0] == ‘i‘) insert(a); if (str[0] == ‘r‘) remove(a); if (str[0] == ‘q‘) ask(a); //debug(); } } return 0; }
POJ3580SuperMemo
有个特殊的操作,右移,和上题差不多,分成两段,然后重新相连
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<iostream> #include<string.h> #include<queue> #include<stack> #include<list> #include<stdlib.h> #include<algorithm> #include<vector> #include<map> #include<cstring> #include<set> #include <fstream> using namespace std; #define keytree ch[ ch[root][1]][0] const int INF = 1e9; const int maxn = 1e6 + 10; int root, tot, top2; int pre[maxn], colorrev[maxn], coloradd[maxn], Size[maxn], Min[maxn], val[maxn]; int ss[maxn], que[maxn]; int ch[maxn][2], a1[maxn]; void newnode(int &x, int fa, int key) { //x = ++tot; if (top2) x = ss[--top2]; else x = ++tot; pre[x] = fa; ch[x][0] = ch[x][1] = 0; val[x] = key; Min[x] = key; colorrev[x] = 0; coloradd[x] = 0; Size[x] = 1; // 不初始化的话,若每次插入用splay翻上去也是对的,更新的时候Size[x] = Size[0]+1 } void downrev(int r) { if (r == 0)return; swap(ch[r][0], ch[r][1]); colorrev[r] ^= 1; } void downadd(int r, int v) { if (r == 0) return; Min[r] += v; val[r] += v; coloradd[r] += v; } void down(int rt) { if (colorrev[rt]) { downrev(ch[rt][0]); downrev(ch[rt][1]); colorrev[rt] = 0; } if (coloradd[rt]) { downadd(ch[rt][0], coloradd[rt]); downadd(ch[rt][1], coloradd[rt]); coloradd[rt] = 0; } } void up(int rt) { int ll = ch[rt][0]; int rr = ch[rt][1]; Min[rt] = min(val[rt], min(Min[ll], Min[rr])); Size[rt] = Size[ll] + Size[rr] + 1; } void Treaval(int x) { if (x) { down(x); Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d Min=%2d \n", x, ch[x][0], ch[x][1], pre[x], Size[x], val[x], Min[x]); Treaval(ch[x][1]); } } void debug() { printf("%d\n", root); Treaval(root); } inline void erase(int x) {//把以x为祖先结点删掉放进内存池,回收内存 int father = pre[x]; int head = 0, tail = 0; for (que[tail++] = x; head < tail; head++) { ss[top2++] = que[head]; if (ch[que[head]][0]) que[tail++] = ch[que[head]][0]; if (ch[que[head]][1]) que[tail++] = ch[que[head]][1]; } ch[father][ch[father][1] == x] = 0; up(father); } void rotate(int x, int kind) { int y = pre[x]; down(y); down(x); ch[y][!kind] = ch[x][kind]; pre[ch[x][kind]] = y; if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x; ch[x][kind] = y; pre[x] = pre[y]; pre[y] = x; up(y); } inline void splay(int x, int goal) { down(x); while (pre[x] != goal) { if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x); else { int y = pre[x]; int z = pre[y]; //down(z); down(y); down(x); //先down z 减少 rotateto 里面的 down y ,x 次数 int kind = ch[z][0] == y; if (ch[y][kind] == x) { rotate(x, !kind); rotate(x, kind); } else { rotate(y, kind); rotate(x, kind); } } } up(x); if (goal == 0) root = x; } int getpos(int k) { int r = root; down(r); while (Size[ch[r][0]] != k) { if (k < Size[ch[r][0]]) r = ch[r][0]; else { k -= Size[ch[r][0]] + 1; r = ch[r][1]; } down(r); } return r; } void build(int &x, int l, int r, int fa) { if (l > r) return; int mid = (l + r) >> 1; newnode(x, fa, a1[mid]); build(ch[x][0], l, mid - 1, x); build(ch[x][1], mid + 1, r, x); up(x); } void rotateto(int x, int goal) { int pos = getpos(x); splay(pos, goal); //傻逼了 pos 写成x } void add(int L, int R, int c) { L--; R++; rotateto(L, 0); rotateto(R, root); downadd(keytree, c); } void revolve(int L, int R, int T) { int ll = L, rr = R; L--; R = R - T; R++; rotateto(L, 0); rotateto(R, root); int t = keytree; ch[ch[root][1]][0] = 0; int len = rr - T - ll + 1; rr -= len; rotateto(rr, 0); rotateto(rr + 1, root); ch[ch[root][1]][0] = t; pre[t] = ch[root][1]; } void reverse(int L, int R) { L--; R++; rotateto(L, 0); rotateto(R, root); downrev(keytree); } void insert(int x, int p) { rotateto(x, 0); rotateto(x + 1, root); newnode(ch[ch[root][1]][0], ch[root][1], p); //傻逼了 ch[root][1] ->root; } void Delete(int x) { int L = x - 1; int R = x + 1; rotateto(L, 0); rotateto(R, root); erase(ch[ch[root][1]][0]); } void askmin(int L, int R) { L--; R++; rotateto(L, 0); rotateto(R, root); printf("%d\n", Min[keytree]); } void init(int n) { Size[0] = colorrev[0] = coloradd[0] = val[0] = ch[0][0] = ch[0][1] = val[0] = 0; Min[0] = INF; tot = top2 = root = 0; newnode(root, 0, -1); newnode(ch[root][1], root, -1); build(keytree, 0, n - 1, ch[root][1]); } int main() { int n; int a, b, c, m; char str[10]; while (scanf("%d", &n) != EOF) { for (int i = 0; i < n; i++) scanf("%d", &a1[i]); init(n); scanf("%d", &m); while (m--) { scanf("%s", str); if (str[0] == ‘A‘) { scanf("%d%d%d", &a, &b, &c); add(a, b, c); } if (str[0] == ‘R‘&&str[3] == ‘E‘) { scanf("%d%d", &a, &b); reverse(a, b); //debug(); continue; } if (str[0] == ‘R‘) { scanf("%d%d%d", &a, &b, &c); c %= (b - a + 1); revolve(a, b, c); } if (str[0] == ‘I‘) { scanf("%d%d", &a, &b); insert(a, b); } if (str[0] == ‘D‘) { scanf("%d", &a); Delete(a); } if (str[0] == ‘M‘) { scanf("%d%d", &a, &b); askmin(a, b); } //debug(); } } return 0; }
文本编辑器editor
没有维修数列复杂,多写写,练手
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<iostream> #include<string.h> #include<queue> #include<stack> #include<list> #include<stdlib.h> #include<algorithm> #include<vector> #include<map> #include<cstring> #include<set> #include <fstream> using namespace std; #define keytree ch[ ch[root][1]][0] const int maxn = 2*1024 * 1024 + 20; int ch[maxn][2], Size[maxn]; int color[maxn], pre[maxn]; char val[maxn]; int tot, root; int pos; void Treaval(int x) { if (x) { Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %d val = %c \n", x, ch[x][0], ch[x][1], pre[x], Size[x], val[x]); Treaval(ch[x][1]); } } void debug() { printf("%d\n", root); Treaval(root); } void up(int x) { int ll = ch[x][0]; int rr = ch[x][1]; Size[x] = Size[ll] + Size[rr] + 1; } void down(int x) { if (color[x]) { swap(ch[x][0], ch[x][1]); color[ch[x][0]] ^= 1; color[ch[x][1]] ^= 1; color[x] = 0; } } void newnode(int &r, int fa, char key) { r = ++tot; pre[r] = fa; ch[r][0] = ch[r][1] = 0; val[r] = key; Size[r] = 1; color[r] = 0; } void rotate(int x, int kind) { int y = pre[x]; down(y); down(x); ch[y][!kind] = ch[x][kind]; pre[ch[x][kind]] = y; if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x; ch[x][kind] = y; pre[x] = pre[y]; pre[y] = x; up(y); } inline void splay(int x, int goal) { down(x); while (pre[x] != goal) { if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x); else { int y = pre[x]; int z = pre[y]; down(z); down(y); down(x); //先down z 减少 rotateto 里面的 down y ,x 次数 int kind = ch[z][0] == y; if (ch[y][kind] == x) { rotate(x, !kind); rotate(x, kind); } else { rotate(y, kind); rotate(x, kind); } } } up(x); if (goal == 0) root = x; } int getpos(int k) { int r = root; down(r); while (Size[ch[r][0]] != k) { if (k < Size[ch[r][0]]) r = ch[r][0]; else { k -= Size[ch[r][0]] + 1; r = ch[r][1]; } down(r); } return r; } void rotateto(int x, int goal) { int t = getpos(x); splay(t, goal); } void Delete(int n) { int ll = pos + 1; int rr = pos + n; //debug(); //printf("%d %djiji\n", rr,getpos(rr+1)); system("pause"); rotateto(ll - 1, 0); rotateto(rr + 1, root); //debug(); system("pause"); ch[ch[root][1]][0] = 0; //up(ch[root][1]); //up(root); } void rev(int n) { int ll = pos + 1; int rr = pos + n; rotateto(ll - 1, 0); rotateto(rr + 1, root); color[keytree] ^= 1; } void prev() { pos--; } void next() { pos++; } void move(int k) { pos = k; } int getrt() { int r = root; down(r); r = ch[r][1]; down(r); while (ch[r][0]) { r = ch[r][0]; down(r); } return r; } void build(int &x, int l, int r, int fa, char str[]) { if (l > r) return; int mid = (l + r) >> 1; newnode(x, fa, str[mid]); build(ch[x][0], l, mid - 1, x, str); build(ch[x][1], mid + 1, r, x, str); up(x); } void insert(int n, char str[]) { rotateto(pos, 0); int rt = getrt(); build(ch[rt][0], 0, n - 1, rt, str); splay(ch[rt][0], 0); } void init() { tot = root = 0; Size[0] = color[0] = ch[0][0] = ch[0][1] = 0; pre[0] = 0; newnode(root, 0, ‘a‘); newnode(ch[root][1], root, ‘a‘); } void gao() { int t = pos + 1; int cc = getpos(t); printf("%c\n", val[cc]); } char s[maxn]; int main() { int T, n; char str[20], gg; while (scanf("%d", &T) != EOF) { init(); while (T--) { scanf("%s", str); if (str[0] == ‘M‘) { scanf("%d", &n); move(n); } if (str[0] == ‘I‘) { scanf("%d%c", &n, &gg); gets(s); insert(n, s); } if (str[0] == ‘D‘) { scanf("%d", &n); Delete(n); } if (str[0] == ‘R‘) { scanf("%d", &n); rev(n); } if (str[0] == ‘G‘) { gao(); } if (str[0] == ‘P‘) { prev(); } if (str[0] == ‘N‘) { next(); } } } return 0; }
HDU3487Play with Chain
有个cut操作,也是先删除,然后插入。
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<iostream> #include<string.h> #include<queue> #include<stack> #include<list> #include<stdlib.h> #include<algorithm> #include<vector> #include<map> #include<set> #include <fstream> using namespace std; #define keytree ch[ ch[root][1]][0] const int maxn = 3e5 + 20; int tot, root; int ch[maxn][2], pre[maxn], color[maxn], Size[maxn], val[maxn]; int n; void Treaval(int x) { if (x) { Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %d val = %d \n", x, ch[x][0], ch[x][1], pre[x], Size[x],val[x]); Treaval(ch[x][1]); } } void debug() { printf("%d\n", root); Treaval(root); } void newnode(int &r, int fa, int key) { r = ++tot; pre[r] = fa; ch[r][0] = ch[r][1] = 0; color[r] = 0; val[r] = key; Size[r] = 1; } void down(int x) { if (color[x]) { swap(ch[x][0], ch[x][1]); int ll = ch[x][0]; int rr = ch[x][1]; color[ll] ^= 1; color[rr] ^= 1; color[x] = 0; } } void up(int x) { int ll = ch[x][0]; int rr = ch[x][1]; Size[x] = Size[ll] + Size[rr] + 1; } int getpos(int k) { int r = root; down(r); while (Size[ch[r][0]] != k) { if (k < Size[ch[r][0]]) r = ch[r][0]; else { k -= Size[ch[r][0]] + 1; r = ch[r][1]; } down(r); } return r; } void rotate(int x, int kind) { int y = pre[x]; down(y); down(x); ch[y][!kind] = ch[x][kind]; pre[ch[x][kind]] = y; if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x; ch[x][kind] = y; pre[x] = pre[y]; pre[y] = x; up(y); } inline void splay(int x, int goal) { down(x); while (pre[x] != goal) { if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x); else { int y = pre[x]; int z = pre[y]; down(z); down(y); down(x); //先down z 减少 rotateto 里面的 down y ,x 次数 int kind = ch[z][0] == y; if (ch[y][kind] == x) { rotate(x, !kind); rotate(x, kind); } else { rotate(y, kind); rotate(x, kind); } } } up(x); if (goal == 0) root = x; } void rotateto(int x, int goal) { int t = getpos(x); splay(t, goal); } void build(int &x, int l, int r, int fa) { if (l > r) return; int mid = (l + r) >> 1; newnode(x, fa, mid); build(ch[x][0], l, mid - 1,x); build(ch[x][1], mid + 1, r,x); up(x); } void init() { root = tot = 0; Size[0] = 0; color[0] = 0; val[0] = 0; ch[0][1] = ch[0][0] = 0; newnode(root, 0, -1); newnode(ch[root][1], root, -1); build(keytree, 1, n, ch[root][1]); } void flip(int L, int R) { rotateto(L - 1, 0); rotateto(R + 1, root); color[keytree] ^= 1; //splay(keytree, 0); } void insert(int rt) { int r = root; down(r); if (ch[r][1]) r = ch[r][1]; down(r); while (ch[r][0]) { r = ch[r][0]; down(r); } ch[r][0] = rt; pre[rt] = r; up(r); } void cut(int L, int R, int pos) { rotateto(L - 1, 0); rotateto(R + 1, root); int cc = keytree; ch[ch[root][1]][0] = 0; rotateto(pos, 0); insert(cc); splay(cc, 0); // 这里要翻上去 } int ans[maxn]; int cnt = 0; void show(int root) { if (root) { down(root); show(ch[root][0]); if (root != 1 && root != 2) ans[cnt++] = val[root]; show(ch[root][1]); } } int main() { int m; char str[10]; int a, b, c; while (scanf("%d%d", &n, &m) != EOF) { cnt = 0; if (n == -1 && m == -1) break; init(); while (m--) { scanf("%s", str); if (str[0] == ‘C‘) { scanf("%d%d%d", &a, &b, &c); cut(a, b, c); } else { scanf("%d%d", &a, &b); flip(a, b); } } show(root); for (int i = 0; i < cnt; i++) { if (i) printf(" "); printf("%d", ans[i]); } cout << endl; } return 0; }
HDU1890Robotic Sort
先排序,然后保存下位置。
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<iostream> #include<string.h> #include<queue> #include<stack> #include<list> #include<stdlib.h> #include<algorithm> #include<vector> #include<map> #include<set> #include <fstream> using namespace std; #define keytree ch[ ch[root][1]][0] const int maxn = 1e5 + 20; int tot, root; int n; int pre[maxn], ch[maxn][2], color[maxn], pos[maxn], Size[maxn], a[maxn]; int val[maxn]; void down(int x) { if (color[x]) { swap(ch[x][0], ch[x][1]); int ll = ch[x][0]; int rr = ch[x][1]; color[ll] ^= 1; color[rr] ^= 1; color[x] = 0; } } void newnode(int &r, int fa, int key) { r = ++tot; pre[r] = fa; ch[r][0] = ch[r][1] = 0; color[r] = 0; Size[r] = 1; pos[key] = r; val[r] = key; } void up(int x) { int ll = ch[x][0]; int rr = ch[x][1]; Size[x] = Size[ll] + Size[rr] + 1; } void rotate(int x, int kind) { int y = pre[x]; down(y); down(x); ch[y][!kind] = ch[x][kind]; pre[ch[x][kind]] = y; if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x; ch[x][kind] = y; pre[x] = pre[y]; pre[y] = x; up(y); } inline void splay(int x, int goal) { down(x); while (pre[x] != goal) { if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x); else { int y = pre[x]; int z = pre[y]; down(z); down(y); down(x); //先down z 减少 rotateto 里面的 down y ,x 次数 int kind = ch[z][0] == y; if (ch[y][kind] == x) { rotate(x, !kind); rotate(x, kind); } else { rotate(y, kind); rotate(x, kind); } } } up(x); if (goal == 0) root = x; } int getpos(int k) { int x = root; for(;;){ down(x); if(Size[ch[x][0]]==k) break; if(k<Size[ch[x][0]]){ x = ch[x][0] ; } else{ k -= Size[ch[x][0]] + 1; x = ch[x][1] ; } } return x; } void build(int &x, int fa, int l, int r) { if (l > r) return; int mid = (l + r) >> 1; newnode(x, fa, a[mid]); build(ch[x][0], x, l, mid - 1); build(ch[x][1], x, mid + 1, r); up(x); } void update(int x) { int t; splay(pos[x], 0); printf("%d", Size[ch[root][0]] + x - 1); int l = 1; int r = getpos(Size[ch[root][0]] + 1); splay(l, 0); splay(r, root); color[keytree] ^= 1; t = getpos(2); splay(1, 0); splay(t, root); ch[ch[root][1]][0] = 0; } void init() { Size[0] = pre[0] = ch[0][1] = ch[0][0] = color[0] = 0; tot = root = 0; newnode(root, 0, 0); newnode(ch[root][1], root, 0); build(keytree, ch[root][1], 1, n); } struct Node { int val; int id; }b[maxn]; int cmp(const Node &a, const Node &b) { return a.val != b.val ? a.val < b.val : a.id < b.id; } void gao() { for (int i = 1; i <= n; i++) b[i].val = a[i], b[i].id = i; sort(b + 1, b + 1 + n, cmp); for (int i = 1; i <= n; i++) { int t = b[i].id; a[t] = i; } } int main() { while (scanf("%d", &n) && n) { for (int i = 1; i <= n; i++) scanf("%d", &a[i]); gao(); init(); for (int i = 1; i <= n; i++) { if (i != 1) printf(" "); update(i); } cout << endl; } return 0; }
poj3468A Simple Problem with Integers
求区间和,值得学习的是建树方式。
#define _CRT_SECURE_NO_WARNINGS #pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <string> #include <vector> #include <cmath> #include <queue> #include <map> #include <time.h> #include <set> using namespace std; const int maxn = 1e5 + 20; int tot, root, n; int ch[maxn][2], pre[maxn], Size[maxn], aa[maxn]; typedef long long LL; LL sum[maxn], val[maxn], color[maxn]; void newnode(int &r, int fa, int k) { r = ++tot; ch[r][0] = ch[r][1] = 0; pre[r] = fa; sum[r] = k; color[r] = 0; Size[r] = 1; val[r] = k; } void up(int x) { int ll = ch[x][0]; int rr = ch[x][1]; sum[x] = sum[ll] + sum[rr] + val[x]; Size[x] = Size[ll] + Size[rr] + 1; } void down(int x) { if (color[x]) { int ll = ch[x][0]; int rr = ch[x][1]; color[ll] += color[x]; color[rr] += color[x]; sum[ll] += Size[ll] * color[x]; sum[rr] += color[x] * Size[rr]; val[x] += color[x]; color[x] = 0; } } void rotate(int x, int kind) { int y = pre[x]; down(y); down(x); ch[y][!kind] = ch[x][kind]; pre[ch[x][kind]] = y; if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x; pre[x] = pre[y]; pre[y] = x; ch[x][kind] = y; up(y); } void splay(int x, int goal) { down(x); while (pre[x] != goal) { if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x); else { int y = pre[x]; int z = pre[y]; int kind = ch[z][0] == y; if (ch[y][kind] == x) { rotate(x, !kind); rotate(x, kind); } else { rotate(y, kind); rotate(x, kind); } } } up(x); if (goal == 0) root = x; } void rotateto(int k, int goal) { int r = root; down(r); while (Size[ch[r][0]] != k) { if (k < Size[ch[r][0]]) { r = ch[r][0]; } else { k -= Size[ch[r][0]] + 1; r = ch[r][1]; } down(r); } splay(r, goal); } void build(int &x, int fa, int l, int r) { if (l > r) return; int mid = (l + r) >> 1; newnode(x, fa, aa[mid]); if (l<mid) build(ch[x][0], x, l, mid - 1); if (r>mid) build(ch[x][1], x, mid + 1, r); up(x); } void update(int L, int R, int add) { rotateto(L - 1, 0); rotateto(R + 1, root); int x = ch[root][1]; x = ch[x][0]; color[x] += add; sum[x] += Size[x] * add; splay(x, 0); } void ask(int L, int R) { rotateto(L - 1, 0); rotateto(R + 1, root); int x = ch[root][1]; x = ch[x][0]; printf("%I64d\n", sum[x]); } void init() { root = tot = 0; ch[0][0] = ch[0][1] = pre[0] = Size[0] = color[0] = sum[0] = 0; newnode(root, 0, -1); newnode(ch[root][1], root, -1);; Size[root] = 2; int k = ch[root][1]; build(ch[k][0], k, 0, n - 1); up(k); up(root); } int main() { int m, a, b, c; char str[10]; while (scanf("%d%d", &n, &m) != EOF) { for (int i = 0; i < n; i++) scanf("%d", &aa[i]); init(); while (m--) { scanf("%s", str); if (str[0] == ‘C‘) { scanf("%d%d%d", &a, &b, &c); update(a, b, c); } else { scanf("%d%d", &a, &b); ask(a, b); } } } return 0; }
营业额统计
需要求前驱和后继,仔细想想,先找到左子树,然后一直往右走
#define _CRT_SECURE_NO_WARNINGS #pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <string> #include <vector> #include <cmath> #include <queue> #include <map> #include <time.h> #include <set> typedef long long LL; using namespace std; int tot, root; const int maxn = 1e6 + 10; int pre[maxn], ch[maxn][2], key[maxn]; void newnode(int &r, int fa, int k) { r = ++tot; pre[r] = fa; ch[r][0] = ch[r][1] = 0; key[r] = k; } void rotate(int x, int kind) { int y = pre[x]; ch[y][!kind] = ch[x][kind]; pre[ch[x][kind]] = y; if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x; pre[x] = pre[y]; ch[x][kind] = y; pre[y] = x; } void splay(int r, int goal) { while (pre[r] != goal) { if (pre[pre[r]] == goal) rotate(r, ch[pre[r]][0]==r); else { int y = pre[r]; int kind = ch[pre[y]][0] == y; if (ch[y][kind] == r) { rotate(r, !kind); rotate(r, kind); } else { rotate(y, kind); rotate(r, kind); } } } if (goal == 0) root = r; } void insert(int k) { int r = root; if (root == 0) { newnode(root, 0, k); return; } while (ch[r][key[r] < k]) r = ch[r][key[r] < k]; newnode(ch[r][key[r] < k], r, k); splay(ch[r][key[r]<k], 0); } int askpre() { int r = root; if (ch[r][0]) r = ch[r][0]; while (ch[r][1]) r = ch[r][1]; if (r == root) return 1e9; return key[r]; } int asklast() { int r = root; if (ch[r][1]) r = ch[r][1]; while (ch[r][0]) r = ch[r][0]; if (r == root) return 1e9; return key[r]; } int main() { int a; int n; int ans = 0; scanf("%d", &n); root = tot = 0; for (int i = 0; i < n; i++) { if (scanf("%d", &a) == EOF) a = 0; insert(a); int Min = 1e9; int t = askpre(); int t1 = asklast(); if (t != 1e9) Min = min(Min, abs(a - t)); if (t1 != 1e9) Min = min(Min, abs(a - t1)); if(Min!=1e9) ans += Min; else ans += a; } printf("%d\n", ans); return 0; }