弟弟救我。
原本想今晚不来机房的,结果硬生生写了个平衡树再回去。
SPlay区间翻转,为了防止越界可以在最后面增加一个虚拟节点。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define INF 1<<30
#define N 600050
using namespace std;
int siz[N],tr[N],s[N][2],tag[N],fa[N];
int a[N],rt,cnt,n;
inline void update(int t) { siz[t] = siz[ s[t][0] ] + siz[ s[t][1] ] + 1; }
void rotate(int x,int &k) {
int y = fa[x] , z = fa[y] , l = s[y][0] != x , r = l ^ 1;
if (y == k) k = x; else {
if (s[z][0] == y) s[z][0] = x; else s[z][1] = x; }
fa[x] = z; fa[y] = x; fa[ s[x][r] ] = y;
s[y][l] = s[x][r]; s[x][r] = y;
update(y); update(x);
}
void SPlay(int x) {
while (x != rt) {
int y = fa[x] , z = fa[y];
if (y != rt) {
if ((s[z][0] == y)^(s[y][0] == x))
rotate(x,rt);
else
rotate(y,rt);
}
rotate(x,rt);
}
}
inline void push_down(int t) {
if (!tag[t]) return ;
swap(s[t][0],s[t][1]);
tag[ s[t][0] ] ^= 1;
tag[ s[t][1] ] ^= 1;
tag[t] ^= 1;
}
int kth(int k,int x) {
push_down(x);
int tmp = siz[ s[x][0] ] + 1;
if (tmp == k) return x;
return tmp > k ? kth(k,s[x][0]) : kth(k-tmp,s[x][1]);
}
void build(int l,int r,int &t,int f) {
//if (l > r) return ;
int mid = (l + r) >> 1;
tr[ t=++cnt ] = mid;
fa[t] = f;
siz[t] = 1;
if (l == r) return ;
if (l <= mid-1) build(l,mid-1,s[t][0],t);
if (mid+1 <= r) build(mid+1,r,s[t][1],t);
update(t);
}
inline void solve() {
build(1,n,rt,0);
int tmp = 0 , ans = 0 , deb = 0;
while (( tmp = a[ tr[ deb = kth(1,rt) ] ] ) != 1) {
SPlay(deb);
int p = kth(tmp+1,rt);
SPlay(p);
tag[ s[rt][0] ] ^= 1;
ans++;
}
printf("%d\n",ans);
}
inline void init() {
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
a[++n] = INF;
}
int main()
{
init();
solve();
return 0;
}