题解:CF2135F To the Infinity
更好的阅读体验
学生零太强大了。
下文中
由定义,
又因为
接下来考虑如何比较两个
我们假设
我们声称,
条件 1 的正确性显然。
证明条件 2 等价于证明
\prod\limits_{i = k}^q F(b_i) < F(a_k) 。由于
F 是 Power tower,因此若F(u) > F(v) ,则有F(u) \ge F^x(v) 。由此放缩
\prod\limits_{i = k}^q F(b_i) \le F^n(b_k) 。由于x \to +\infty ,因此F^n(b_k) < F^x(b_k) < F(a_k) ,得证。
这样问题就简单了许多。
我们仍然无法直接比较两个
同时有一个很好的性质:一个点的
具体地,我们维护一个小根堆,每次取出堆顶
我们用主席树维护哈希值,可以方便地二分一个后缀比较两个序列字典序的大小。我们对每个点存下
我们取出
重复这个过程就可以求出每个点的
注意到堆的每一次比较都需要调用一次主席树上二分,因此单组数据复杂度为
#include<bits/stdc++.h>
#define endl '\n'
#define N 400006
using namespace std;
using u64=unsigned long long;
int n,tp,deg[N],rt[N],l[N],r[N],fa[N],rk[N],ans[N];
u64 pw[N];
struct HJT {
int tot,ls[N<<5],rs[N<<5];
struct Node {
u64 hs; int sz;
Node(u64 hs=0,int sz=0):hs(hs),sz(sz) {}
friend Node operator +(Node x,Node y)
{
Node ret;
ret.sz=x.sz+y.sz,ret.hs=x.hs*pw[y.sz]+y.hs;
return ret;
}
} tree[N<<5];
void clear()
{
for(int i=1;i<=tot;i++)ls[i]=rs[i]=0,tree[i]=Node();
tot=0;
}
void update(int &p,int q,int l,int r,int k)
{
p=++tot;
tree[p]=tree[q],ls[p]=ls[q],rs[p]=rs[q];
if(l==r)return tree[p]=tree[p]+Node(l,1),(void)0;
int mid=l+r>>1;
k<=mid?update(ls[p],ls[q],l,mid,k):
update(rs[p],rs[q],mid+1,r,k);
tree[p]=tree[ls[p]]+tree[rs[p]];
}
int cmp(int p,int q,int l,int r,int rp,int rq)
{
if(tree[p].hs==tree[q].hs)return rp>rq;
if(!p||!q||l==r)return tree[p].sz>tree[q].sz;
int mid=l+r>>1;
u64 hs_rp=tree[rs[p]].hs,hs_rq=tree[rs[q]].hs;
if(hs_rp==hs_rq)return cmp(ls[p],ls[q],l,mid,rp,rq);
return cmp(rs[p],rs[q],mid+1,r,rp,rq);
}
} T;
struct Data {
int u;
Data(int u):u(u) {}
friend bool operator >(Data x,Data y) {return T.cmp(rt[x.u],rt[y.u],1,n,x.u,y.u);}
};
inline int eq(int u,int v) {return T.tree[rt[u]].hs==T.tree[rt[v]].hs;}
priority_queue<Data,vector<Data>,greater<Data> > q;
void solve()
{
scanf("%d",&n),T.clear(),tp=0;
while(q.size())q.pop();
for(int i=1;i<=n;i++)deg[i]=rt[i]=l[i]=r[i]=fa[i]=rk[i]=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&l[i],&r[i]);
if(l[i])fa[l[i]]=fa[r[i]]=i,deg[i]=2;
else T.update(rt[i],0,1,n,rk[i]=1),q.push(i),deg[i]=0;
}
while(q.size())
{
int u=q.top().u; q.pop();
rk[u]=rk[ans[tp]]+!eq(ans[tp],u),ans[++tp]=u;
if(!--deg[fa[u]])
T.update(rt[fa[u]],rt[l[fa[u]]],1,n,rk[r[fa[u]]]),q.push(fa[u]);
}
for(int i=1;i<=n;i++)
printf("%d%c",ans[i]," \n"[i==n]);
}
main()
{
int T; scanf("%d",&T),pw[0]=1;
for(int i=1;i<N;i++)pw[i]=pw[i-1]*1145141;
while(T--)solve();
return 0;
}