P3165 [CQOI2014]排序机械臂
一道Splay模板题,只不过需要注意一些细节
直接上代码
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int N = 1e5 + 5, INF = 0x3f3f3f3f;
typedef pair<int, int> PII;
struct tree
{
int s[2], v, p, siz, lz;
void init(int _v, int _p)
{
v = _v, p = _p, siz = 1;
}
} tr[N];
int root, idx, hi[N];
PII poi[N];
bool cmp(PII a, PII b)
{
if (a.first == b.first)
return a.second < b.second;
return a.first < b.first;
}//注意排序规则
void pushup(int p)
{
tr[p].siz = tr[tr[p].s[0]].siz + tr[tr[p].s[1]].siz + 1;
}
void pushdown(int p)
{
if (tr[p].lz)
{
tr[p].lz = 0;
if (tr[p].s[0])
tr[tr[p].s[0]].lz ^= 1;
if (tr[p].s[1])
tr[tr[p].s[1]].lz ^= 1;
swap(tr[p].s[0], tr[p].s[1]);
}
}
int build(int l, int r, int p)
{
int mid = (l + r) >> 1;
tr[mid].init(hi[mid], p), poi[mid] = {hi[mid], mid};
if (l < mid)
tr[mid].s[0] = build(l, mid - 1, mid);
if (r > mid)
tr[mid].s[1] = build(mid + 1, r, mid);
pushup(mid);
return mid;
}
void rotate(int x)
{
int y = tr[x].p, z = tr[y].p;
pushdown(y), pushdown(x);//下传标记
int k = tr[y].s[1] == x;
tr[z].s[tr[z].s[1] == y] = x, tr[x].p = z;
tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].p = y;
tr[x].s[k ^ 1] = y, tr[y].p = x;
pushup(y), pushup(x);
}
void splay(int x, int k)
{
while (tr[x].p != k)
{
int y = tr[x].p, z = tr[y].p;
pushdown(z), pushdown(y), pushdown(x);//提前下传标记
if (z != k)
{
if ((tr[y].s[1] == x) ^ (tr[z].s[1] == y))
rotate(x);
else
rotate(y);
}
rotate(x);
}
if (!k)
root = x;
}
int get_k(int k)
{
int u = root;
while (u)
{
pushdown(u);
if (tr[tr[u].s[0]].siz >= k)
u = tr[u].s[0];
else if (tr[tr[u].s[0]].siz + 1 == k)
return u;
else
k -= tr[tr[u].s[0]].siz + 1, u = tr[u].s[1];
}
return -1;
}
void reverse(int ll, int rr)
{
int l = get_k(ll), r = get_k(rr + 2);
splay(l, 0), splay(r, l);
tr[tr[r].s[0]].lz ^= 1;
}
int main()
{
int n;
scanf("%d", &n);
hi[1] = -INF, hi[n + 2] = INF;//下标从1开始
for (int i = 2; i <= n + 1; i++)
scanf("%d", &hi[i]);
root = build(1, n + 2, 0);
sort(poi + 1, poi + n + 3, cmp);
for (int i = 2; i <= n + 1; i++)
{
int u = poi[i].second;
splay(u, 0);
int x = tr[tr[u].s[0]].siz + 1;
printf("%d ", x - 1);
reverse(i - 1, x - 1);
}
return 0;
}