Description
Input
Output
Sample Input
6 3 4 5 1 6 2 4 3 3 2 1 0
Sample Output
4 6 4 5 6 64 2 4 4
作为splay区间反转的第一题,这道题并不难,然而我却花了整整一下午调试还是wa,直到晚上再床上转辗反侧时
才回忆起,是我题意没读清楚,何等sb的错误啊,其实早早就写对了的。顺便一提,第一次做区间反转我直接把整个区间的坐标都算出来了,后来我以为是wa在这,又去网上参考了不少人的想法,后来发现splay本身是平衡树,无论怎么样旋转是不会改变节点之间的相对大小的,所以根本不用算出坐标,反转只要打标记然后交换左右子树就好了,这样写方便一点。此题有重复值,先离散化一发在做。
第一次写的计算标号的
#include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<vector> #include<iostream> #include<algorithm> #include<bitset> #include<functional> using namespace std; typedef unsigned long long ull; typedef long long LL; const int maxn = 1e5 + 10; int n, m, l, r, c, root, a[maxn]; char s[10]; struct point { int x, id; bool operator<(const point&a)const{ return x == a.x ? id < a.id : x < a.x; } }b[maxn]; struct Splays { const static int maxn = 1e5 + 10; const static int INF = 0x7FFFFFFF; int ch[maxn][2], F[maxn], U[maxn], C[maxn], A[maxn], sz, G[maxn], S[maxn]; int Node(int f, int u, int c) { S[sz] = 1; C[sz] = A[sz] = c; G[sz] = ch[sz][0] = ch[sz][1] = 0; F[sz] = f; U[sz] = u; return sz++; } void clear(){ sz = 1; ch[0][0] = ch[0][1] = A[0] = U[0] = F[0] = G[0] = 0; C[0] = INF; S[0] = 1; } void Pushdown(int x) { if (!G[x]) return; if (ch[x][0]) { U[ch[x][0]] = G[x] + S[x] * U[ch[x][0]]; G[ch[x][0]] = G[x] + S[x] * G[ch[x][0]]; S[ch[x][0]] *= S[x]; } if (ch[x][1]) { U[ch[x][1]] = G[x] + S[x] * U[ch[x][1]]; G[ch[x][1]] = G[x] + S[x] * G[ch[x][1]]; S[ch[x][1]] *= S[x]; } if (S[x] < 0) swap(ch[x][0], ch[x][1]); G[x] = 0; S[x] = 1; } void rotate(int x, int k) { int y = F[x]; ch[y][!k] = ch[x][k]; F[ch[x][k]] = y; if (F[y]) ch[F[y]][y == ch[F[y]][1]] = x; F[x] = F[y]; F[y] = x; ch[x][k] = y; C[x] = C[y]; C[y] = min(A[y], min(C[ch[y][1]], C[ch[y][0]])); } void Splay(int x, int r) { for (int fa = F[r]; F[x] != fa;) { if (F[F[x]] == fa) { rotate(x, x == ch[F[x]][0]); return; } int y = x == ch[F[x]][0], z = F[x] == ch[F[F[x]]][0]; y^z ? (rotate(x, y), rotate(x, z)) : (rotate(F[x], z), rotate(x, y)); } } void insert(int &x, int u) { for (int i = x; i; i = ch[i][U[i] < u]) { Pushdown(i); if (u == U[i]){ Splay(i, x); x = i; break; } } } void find(int &x, int u) { insert(x, u - 1); int now = 0; for (int i = ch[x][1]; i;) { Pushdown(i); if (C[ch[i][1]] == C[i]) { i = ch[i][1]; continue; } if (A[i] == C[i]) { now = i; break; } if (C[ch[i][0]] == C[i]) { i = ch[i][0]; continue; } } printf("%d", U[now]); insert(ch[x][1], U[now] + 1); G[ch[ch[x][1]][0]] = (u + U[now]) - G[ch[ch[x][1]][0]]; S[ch[ch[x][1]][0]] *= -1; U[ch[ch[x][1]][0]] = (u + U[now]) - U[ch[ch[x][1]][0]]; } void build(int fa, int &x, int l, int r) { if (l > r) return; if (l == r) { x = Node(fa, l, a[l]); return; } int mid = l + r >> 1; x = Node(fa, mid, a[mid]); build(x, ch[x][0], l, mid - 1); build(x, ch[x][1], mid + 1, r); C[x] = min(A[x], min(C[ch[x][0]], C[ch[x][1]])); } }solve; int main() { while (scanf("%d", &n) != EOF, n) { solve.clear(); a[0] = root = 0; a[n + 1] = 0x7FFFFFFF; for (int i = 1; i <= n; i++) scanf("%d", &b[i].x), b[i].id = i; sort(b + 1, b + n + 1); for (int i = 1; i <= n; i++) a[b[i].id] = i; solve.build(0, root, 0, n + 1); for (int i = 1; i <= n; i++) { solve.find(root, i); printf("%s", i == n ? "\n" : " "); } } return 0; }
后来写的直接反转区间,然后把之前节点删除的做法#include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<vector> #include<iostream> #include<algorithm> #include<bitset> #include<functional> using namespace std; typedef unsigned long long ull; typedef long long LL; const int maxn = 2e5 + 10; int n, m, l, r, c, root, a[maxn]; char s[10]; struct point { int x, id; bool operator<(const point&a)const{ return x == a.x ? id < a.id : x < a.x; } }b[maxn]; struct Splays { const static int maxn = 2e5 + 10; const static int INF = 0x7FFFFFFF; int ch[maxn][2], F[maxn], sz; int C[maxn], A[maxn], R[maxn], S[maxn]; int Node(int f, int c) { R[sz] = ch[sz][0] = ch[sz][1] = 0; F[sz] = f; C[sz] = A[sz] = c; S[sz] = 1; return sz++; } void clear(){ sz = 1; ch[0][0] = ch[0][1] = F[0] = 0; C[0] = INF; S[0] = 0; } void pushdown(int x) { if (!R[x]) return; R[ch[x][0]] ^= 1; R[ch[x][1]] ^= 1; swap(ch[x][0], ch[x][1]); R[x] = 0; } void rotate(int x, int k) { int y = F[x]; ch[y][!k] = ch[x][k]; F[ch[x][k]] = y; if (F[y]) ch[F[y]][y == ch[F[y]][1]] = x; F[x] = F[y]; F[y] = x; ch[x][k] = y; C[x] = C[y]; C[y] = min(min(C[ch[y][0]], C[ch[y][1]]), A[y]); S[x] = S[y]; S[y] = S[ch[y][0]] + S[ch[y][1]] + 1; } void Splay(int x, int r) { for (int fa = F[r]; F[x] != fa;) { if (F[F[x]] == fa) { rotate(x, x == ch[F[x]][0]); return; } int y = (x == ch[F[x]][0]), z = (F[x] == ch[F[F[x]]][0]); y^z ? (rotate(x, y), rotate(x, z)) : (rotate(F[x], z), rotate(x, y)); } } void build(int f, int&x, int l, int r) { if (l > r) return; int mid = l + r >> 1; x = Node(f, a[mid]); build(x, ch[x][0], l, mid - 1); build(x, ch[x][1], mid + 1, r); C[x] = min(min(C[ch[x][0]], C[ch[x][1]]), A[x]); S[x] += S[ch[x][0]] + S[ch[x][1]]; } void find(int &x, int k) { for (int i = x; i;) { pushdown(i); if (C[i] == C[ch[i][1]]) { i = ch[i][1]; continue; } if (C[i] == A[i]) { Splay(i, x); x = i; break; } i = ch[i][0]; } printf("%d%s", k + S[ch[x][0]], k == n ? "\n" : " "); if (!ch[x][0]) { x = ch[x][1]; F[x] = 0; return; } R[ch[x][0]] ^= 1; for (int i = ch[x][0]; i; i = ch[i][1]) { pushdown(i); if (!ch[i][1]) { Splay(i, x); x = i; break; } } ch[x][1] = ch[ch[x][1]][1]; F[ch[x][1]] = x; S[x]--; C[x] = min(min(C[ch[x][0]], C[ch[x][1]]), A[x]); } }solve; int main() { while (scanf("%d", &n) != EOF, n) { solve.clear(); root = 0; for (int i = 1; i <= n; i++) scanf("%d", &b[i].x), b[i].id = i; sort(b + 1, b + n + 1); for (int i = 1; i <= n; i++) a[b[i].id] = i; solve.build(0, root, 1, n); for (int i = 1; i <= n; i++) solve.find(root, i); } return 0; }