题意
有一个长度为n的序列,序列为n的一个排列。每次找到序列的第一个数k,若k=1则退出,否则区间[1,k]进行翻转,直至k=1或翻转次数大于100000。n<=300000
这题是Splay翻转裸题,但是,我调了一个晚上,毕竟很久没有打过Splay。
问题是出在一开始构建Splay的过程之中,没有建最大最小的点,而我是用数组写的,第0位设为空,在翻转的过程中,很容易就跑到第0位去了,然后无限TLE,一定要吸取教训啊。
#include <cstdio> #include <cstdlib> #include <algorithm> using namespace std; #define ls(x) (ch[x][0]) #define rs(x) (ch[x][1]) const int maxn = 300005; int n, a[maxn]; struct Tree { int ch[maxn][2], siz[maxn], rev[maxn], fa[maxn], val[maxn], cnt, root; Tree() { root = cnt = 0; } void new_node(int &x, int c) { x = ++cnt; ch[x][0] = ch[x][1] = fa[x] = rev[x] = 0; siz[x] = 1; val[x] = c; } void pushup(int x) { siz[x] = siz[ls(x)]+siz[rs(x)]+1; } void pushdown(int x) { if (rev[x] == 0) return ; swap(ls(x), rs(x)); rev[ls(x)] ^= rev[x], rev[rs(x)] ^= rev[x]; rev[x] = 0; } void build(int &x, int l, int r, int f) { if (l > r) return ; int mid = (l+r)>>1; new_node(x, a[mid]); build(ls(x), l, mid-1, x); build(rs(x), mid+1, r, x); fa[x] = f; pushup(x); } void rotate(int x, int f) { int y = fa[x]; pushdown(x); fa[ch[x][!f]] = y; ch[y][f] = ch[x][!f]; fa[x] = fa[y]; if (fa[y]) ch[fa[y]][ls(fa[y]) == y ? 0 : 1] = x; ch[x][!f] = y; fa[y] = x; pushup(y); } void splay(int x, int goal) { pushdown(x); while (fa[x] != goal) { int y = fa[x], z = fa[y]; if (z == goal) { rotate(x, ls(y) == x ? 0 : 1); break ; } int f = ls(z) == y ? 0 : 1; if (ch[y][f] == x) rotate(y, f), rotate(x, f); else rotate(x, !f), rotate(x, f); } pushup(x); if (goal == 0) root = x; } void rotateto(int k, int goal) { int x = root; pushdown(x); while (siz[ls(x)]+1 != k) { if (siz[ls(x)] >= k) x = ls(x); else { k -= siz[ls(x)]+1; x = rs(x); } pushdown(x); } splay(x, goal); } void rever(int k) { rotateto(1, 0); rotateto(k+2, root); rev[ls(rs(root))] ^= 1; } int find(int k) { int x = root; pushdown(x); while (siz[ls(x)]+1 != k) { if (siz[ls(x)] >= k) x = ls(x); else { k -= siz[ls(x)]+1; x = rs(x); } pushdown(x); } return val[x]; } }T; int main() { scanf("%d", &n); for (int i = 2; i <= n+1; ++i) scanf("%d", &a[i]); T.build(T.root, 1, n+2, 0); int k = T.find(2), ans = 0; while (k != 1) { T.rever(k); ans ++; if (ans > 100000) { ans = -1; break ; } k = T.find(2); } printf("%d\n", ans); return 0; }