/*
这题因为不是对数列第K个,而是对初始化标记的序号操作,所以标记的处理很不一般
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100000 + 123;
const int INF = 1 << 28;
struct number
{
int v, ps;
}a[MAXN];
int s[MAXN], root, m, cnt, No[MAXN];
struct node
{
int p, c[2], sz;
bool d, rev;
}T[MAXN];
bool cmp(number a, number b)
{
if(a.v != b.v) return a.v < b.v;
return a.ps < b.ps;
}
void sc(int _p, int _c, int _d)
{
T[_p].c[_d] = _c;
T[_c].p = _p;
T[_c].d = _d;
}
void upd(int x)
{
T[x].sz = T[T[x].c[0]].sz + T[T[x].c[1]].sz + 1;
}
void rot(int x)
{
int y = T[x].p;
bool d = T[x].d;
if(y == root)
{
root = x;
T[root].p = 0;
}
else sc(T[y].p, x, T[y].d);
sc(y, T[x].c[!d], d);
sc(x, y, !d);
upd(y);
}
void splay(int x, int r)
{
int p;
while((p = T[x].p) != r)
{
if(T[p].p == r) rot(x);
else
{
if(T[x].d == T[p].d)
{
rot(p);
rot(x);
}
else
{
rot(x);
rot(x);
}
}
}
upd(x);
}
void newnode(int n)
{
T[n].c[0] = T[n].c[1] = 0;
T[n].sz = 1;
T[n].rev = 0;
}
int mkt(int l, int r)
{
if(l > r) return 0;
int mid= (l + r) >> 1;
newnode(++cnt);
int n0 = cnt, l_r = mkt(l, mid - 1), r_r = mkt(mid + 1, r);
s[mid] = n0;
sc(n0, l_r, 0);
sc(n0, r_r, 1);
upd(n0);
return n0;
}
void prepare()
{
T[0].sz = T[0].c[0] = T[0].c[1] = T[0].p = 0;
T[0].rev = 0;
cnt = 0;
root = mkt(0, m + 1);
T[root].p = 0;
}
void rev_opr(int x)
{
T[x].rev = !T[x].rev;
int c0 = T[x].c[0], c1 = T[x].c[1];
sc(x, c0, 1);
sc(x, c1, 0);
}
void dm(int x)
{
if(T[x].rev)
{
rev_opr(T[x].c[0]);
rev_opr(T[x].c[1]);
T[x].rev = 0;
}
}
int Find_Kth(int k)
{
int i = root, s0;
while(i)
{
dm(i);
s0 = T[T[i].c[0]].sz + 1;
if(k == s0) break;
else if(k < s0) i = T[i].c[0];
else
{
k -= s0;
i = T[i].c[1];
}
}
return i;
}
int succ(int x)
{
int i, j = 0, len0 = 0;
i = x;
while (i)
{
No[len0++] = i;
i = T[i].p;
}
for(int i=len0-1; i>=0; i--) dm(No[i]);
if (T[x].c[1])
{
i = T[x].c[1];
while (dm(i), j = T[i].c[0]) i = j;
return i;
}
else
{
for (int i=len0-1; i>=1; i--)
if (No[i - 1] == T[No[i]].c[0]) j = No[i];
return j;
}
}
void dm_all(int x)
{
int i = x, len0 = 0;
while (i)
{
No[len0++] = i;
i = T[i].p;
}
for(int i = len0 - 1; i>=0; i--) dm(No[i]);
}
int reve(int l, int r)
{
dm_all(r);
splay(l, 0);
splay(r, l);
rev_opr(T[r].c[0]);
return T[T[r].c[0]].sz;
}
int succ()
{
int i = T[root].c[1], j;
if(!i) return 0;
while(j = T[i].c[0]) i = j;
return i;
}
int main()
{
while(1)
{
scanf("%d", &m);
if(!m) break;
for(int i = 1; i <= m; i++)
{
scanf("%d", &a[i].v);
a[i].ps = i;
}
a[0].v = a[m + 1].v = INF;
a[0].ps = 0, a[m + 1].ps = m + 1;
sort(a + 1, a + 1 + m, cmp);
prepare();
for(int i = 1; i <= m; i++)
{
int l = Find_Kth(i);
/*dm_all(s[a[i].ps]); 超时,这么写,可能因为伸展次数过多
splay(s[a[i].ps], 0);
int r = succ(); */
int r = succ(s[a[i].ps]);
printf("%d%c", reve(l, r) + i - 1, i == m ? '\n' : ' ');
}
}
return 0;
}
hdu 1890 Robotic Sort //splay tree
区间反转查询
最新推荐文章于 2022-02-25 21:57:21 发布
本文介绍了一种使用线段树实现区间反转和查询第K小元素的高效算法。通过自定义节点结构和旋转操作来维护树的平衡,实现了对区间内元素的快速反转及后续的查询操作。
1330

被折叠的 条评论
为什么被折叠?



