我不是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也算是一个外挂吧,关键时刻说不定会有用。