我不是code的生产者,我只是code的搬运工。(感谢cxlove世界冠军提供参考代码,我已经成功从中提取了模板= =)
好吧,其实这个除了上一题的模板之外完全是我自己写的,连那个remove函数都是现编的= =
要注意的是数据可能有重复,需要处理一下。
splay中使用rotate函数,用时296MS:
#include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <vector> #include <set> #include <queue> #include <stack> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 100010; int n; int val[maxn], fa[maxn], ch[maxn][2], size[maxn], root, tot; int rev[maxn]; struct node { int v, id; bool operator < (const node &o) const { return (v==o.v && id < o.id) || v < o.v; } }a[maxn]; inline void init() { root = tot = 0; val[0] = fa[0] = ch[0][0] = ch[0][1] = size[0] = 0; rev[0] = 0; } inline void newnode(int x, int value, int father) { val[x] = value; fa[x] = father; ch[x][0] = ch[x][1] = 0; size[x] = 1; rev[x] = 0; } inline void push_down(int x) { if (!rev[x]) return; swap(ch[x][0], ch[x][1]); rev[ch[x][0]] ^= 1; rev[ch[x][1]] ^= 1; rev[x] = 0; } inline void push_up(int x) { size[x] = size[ch[x][0]] + size[ch[x][1]] + 1; } inline void rotate(int x, int kind) { int y = fa[x]; push_down(x); push_down(y); ch[y][kind^1] = ch[x][kind]; fa[ch[x][kind]] = y; if (fa[y]) ch[fa[y]][ch[fa[y]][1]==y] = x; fa[x] = fa[y]; ch[x][kind] = y; fa[y] = x; push_up(y); } inline void splay(int x, int goal) { push_down(x); while (fa[x] != goal) { int y = fa[x]; if (fa[y] == goal) { push_down(y); push_down(x); rotate(x, ch[y][0]==x); } else { push_down(fa[y]); push_down(y); push_down(x); int kind = ch[fa[y]][0]==y; if (ch[y][kind] == x) {rotate(x, kind^1); rotate(x, kind);} else {rotate(y, kind); rotate(x, kind);} } } push_up(x); if (goal == 0) root = x; } inline void remove(int x) { int y = fa[x]; if (!ch[x][0]) { ch[y][ch[y][1]==x] = ch[x][1]; fa[ch[x][1]] = y; } else { int z = ch[x][0]; push_down(z); while (ch[z][1]) { z = ch[z][1]; push_down(z); } splay(z, y); ch[z][1] = ch[x][1]; fa[ch[x][1]] = z; ch[y][ch[y][1]==x] = z; fa[z] = y; } } inline void build(int &x, int l, int r, int father) { if (l > r) return; int mid = (l + r) >> 1; newnode(x = mid, a[mid].v, father); if (l < mid) build(ch[x][0], l, mid-1, x); if (mid < r) build(ch[x][1], mid+1, r, x); push_up(x); } int main() { while (scanf("%d", &n) == 1 && n) { for (int i=1;i<=n;i++) scanf("%d", &a[i].v), a[i].id = i; sort(a+1, a+n+1); init(); build(root, 1, n, 0); for (int i=1;i<n;i++) { int x = a[i].id; splay(x, 0); printf("%d ", size[ch[x][0]] + i); rev[ch[x][0]] ^= 1; remove(root); } printf("%d\n", n); } return 0; }
splay中使用zigzag,用时281MS:
#include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <vector> #include <set> #include <queue> #include <stack> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 100010; int n; int val[maxn], fa[maxn], ch[maxn][2], size[maxn], root, tot; int rev[maxn]; struct node { int v, id; bool operator < (const node &o) const { return (v==o.v && id < o.id) || v < o.v; } }a[maxn]; inline void init() { root = tot = 0; val[0] = fa[0] = ch[0][0] = ch[0][1] = size[0] = 0; rev[0] = 0; } inline void newnode(int x, int value, int father) { val[x] = value; fa[x] = father; ch[x][0] = ch[x][1] = 0; size[x] = 1; rev[x] = 0; } inline void push_down(int x) { if (!rev[x]) return; swap(ch[x][0], ch[x][1]); rev[ch[x][0]] ^= 1; rev[ch[x][1]] ^= 1; rev[x] = 0; } inline void push_up(int x) { size[x] = size[ch[x][0]] + size[ch[x][1]] + 1; } inline void zig(int x) { int y = fa[x], z = fa[y]; ch[y][1] = ch[x][0]; fa[ch[x][0]] = y; ch[x][0] = y; fa[y] = x; fa[x] = z; if (z) ch[z][ch[z][1]==y] = x; push_up(y); } inline void zag(int x) { int y = fa[x], z = fa[y]; ch[y][0] = ch[x][1]; fa[ch[x][1]] = y; ch[x][1] = y; fa[y] = x; fa[x] = z; if (z) ch[z][ch[z][1]==y] = x; push_up(y); } inline void zigzig(int x) { int y = fa[x], z = fa[y], fz = fa[z]; ch[z][1] = ch[y][0]; fa[ch[y][0]] = z; ch[y][1] = ch[x][0]; fa[ch[x][0]] = y; fa[z] = y; ch[y][0] = z; fa[y] = x; ch[x][0] = y; fa[x] = fz; if (fz) ch[fz][ch[fz][1]==z] = x; push_up(z); push_up(y); } inline void zagzag(int x) { int y = fa[x], z = fa[y], fz = fa[z]; ch[z][0] = ch[y][1]; fa[ch[y][1]] = z; ch[y][0] = ch[x][1]; fa[ch[x][1]] = y; fa[z] = y; ch[y][1] = z; fa[y] = x; ch[x][1] = y; fa[x] = fz; if (fz) ch[fz][ch[fz][1]==z] = x; push_up(z); push_up(y); } inline void zigzag(int x) { int y = fa[x], z = fa[y], fz = fa[z]; ch[y][1] = ch[x][0]; fa[ch[x][0]] = y; ch[z][0] = ch[x][1]; fa[ch[x][1]] = z; fa[y] = fa[z] = x; ch[x][0] = y; ch[x][1] = z; fa[x] = fz; if (fz) ch[fz][ch[fz][1]==z] = x; push_up(z); push_up(y); } inline void zagzig(int x) { int y = fa[x], z = fa[y], fz = fa[z]; ch[y][0] = ch[x][1]; fa[ch[x][1]] = y; ch[z][1] = ch[x][0]; fa[ch[x][0]] = z; fa[y] = fa[z] = x; ch[x][1] = y; ch[x][0] = z; fa[x] = fz; if (fz) ch[fz][ch[fz][1]==z] = x; push_up(z); push_up(y); } void splay(int x, int goal) { int y, z; push_down(x); while(fa[x] != goal) { int y = fa[x]; if (fa[y] == goal){ push_down(y); push_down(x); if (ch[y][1] == x) zig(x); else zag(x); } else { z = fa[y]; push_down(z); push_down(y); push_down(x); if (ch[z][1] == y) { if (ch[y][1] == x) zigzig(x); else zagzig(x); } else { if (ch[y][0] == x) zagzag(x); else zigzag(x); } } } push_up(x); if (fa[x] == 0) root=x; } inline void remove(int x) { int y = fa[x]; if (!ch[x][0]) { ch[y][ch[y][1]==x] = ch[x][1]; fa[ch[x][1]] = y; } else { int z = ch[x][0]; push_down(z); while (ch[z][1]) { z = ch[z][1]; push_down(z); } splay(z, y); ch[z][1] = ch[x][1]; fa[ch[x][1]] = z; ch[y][ch[y][1]==x] = z; fa[z] = y; } } inline void build(int &x, int l, int r, int father) { if (l > r) return; int mid = (l + r) >> 1; newnode(x = mid, a[mid].v, father); if (l < mid) build(ch[x][0], l, mid-1, x); if (mid < r) build(ch[x][1], mid+1, r, x); push_up(x); } int main() { while (scanf("%d", &n) == 1 && n) { for (int i=1;i<=n;i++) scanf("%d", &a[i].v), a[i].id = i; sort(a+1, a+n+1); init(); build(root, 1, n, 0); for (int i=1;i<n;i++) { int x = a[i].id; splay(x, 0); printf("%d ", size[ch[x][0]] + i); rev[ch[x][0]] ^= 1; remove(root); } printf("%d\n", n); } return 0; }
所以说,虽然提速不是太多,但是zigzag也算是一个外挂吧,关键时刻说不定会有用。