CQOI2014 排序机械臂
突然发现自己不大会维护位置这种题……学习了一下。
具体的操作还是使用\(fhq-treap\)实现。什么split,merge都一样。问题是如何求位置。
首先我们在读入的时候,保存每个节点的权值和下标,并且按照权值进行排序,同时把它插入到一棵\(fhq-treap\)中。
之后我们怎么查找一个节点所在的位置呢?其实我们相当于找这个节点的排名,也就是其前面有多少。但是这个无法简单的split之后去求解。不过因为\(fhq-treap\)的期望树高是log的,我们可以直接通过暴力跳父亲来计算答案。具体的方法就是,如果你是你父亲的右儿子,那么答案就加上你父亲的左儿子的size+1,之后继续暴力上跳即可。
然后注意在查询之前要走到父亲并且手动全部pushdown一遍。
看一下代码。
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
#define I inline
using namespace std;
typedef long long ll;
const int M = 500005;
I int read()
{
int ans = 0,op = 1;char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
return ans * op;
}
struct node
{
int v,id;
bool operator < (const node &g) const {return v < g.v || (v == g.v && id < g.id);}
}s[M];
struct tree
{
int lc,rc,fa,size,rev,rk;
}t[M];
int n,root,top,sta[M];
I void rever(int x) {t[x].rev ^= 1,swap(t[x].lc,t[x].rc);}
I void pushup(int x)
{
t[x].size = t[t[x].lc].size + t[t[x].rc].size + 1;
t[t[x].lc].fa = x,t[t[x].rc].fa = x;
}
I void pushdown(int x)
{
if(!t[x].rev) return;
if(t[x].lc) rever(t[x].lc);
if(t[x].rc) rever(t[x].rc);
t[x].rev ^= 1;
}
int merge(int x,int y)
{
if(!x || !y) return x | y;
pushdown(x),pushdown(y);
if(t[x].rk < t[y].rk) {t[x].rc = merge(t[x].rc,y),pushup(x);return x;}
else {t[y].lc = merge(x,t[y].lc),pushup(y);return y;}
}
void splits(int u,int k,int &x,int &y)
{
if(!u) {x = y = 0;return;}
pushdown(u);
if(t[t[u].lc].size >= k) y = u,splits(t[u].lc,k,x,t[u].lc);
else x = u,splits(t[u].rc,k-t[t[u].lc].size-1,t[u].rc,y);
pushup(u);
}
int kth(int u)
{
sta[++top] = u;
for(int i = u;t[i].fa;i = t[i].fa) sta[++top] = t[i].fa;
while(top) pushdown(sta[top--]);
int cur = t[t[u].lc].size;
while(u)
{
if(u == t[t[u].fa].rc) cur += t[t[t[u].fa].lc].size + 1;
u = t[u].fa;
}
return cur + 1;
}
void Rever(int l,int r)
{
int x,y,z;
splits(root,r,x,y),splits(x,l-1,x,z);
rever(z),root = merge(merge(x,z),y);
}
int main()
{
srand(time(0));
n = read();
rep(i,1,n) s[i].v = read(),s[i].id = i,t[i].size = 1,t[i].rk = rand(),root = merge(root,i);
sort(s+1,s+1+n);
rep(i,1,n)
{
int k = kth(s[i].id);
printf("%d ",k),Rever(i,k);
}
enter;
return 0;
}
当你意识到,每个上一秒都成为永恒。