【X Round -1 】树上后缀排序(后缀平衡树)

传送门


没有题解:

后缀平衡树裸题。

由于出题人语文不行,请去讨论区查看正确题意。

下面这份代码就是在错的题意下写了之后改的,所以排序部分非常诡异。


代码:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const

using std::cerr;
using std::cout;

cs int N=5e5+7;

int n;

int fa[N],pre[N],bel[N];char s[N];

namespace SGT{
	int siz[N],lc[N],rc[N];
	double L[N],R[N];int *bad,rt;
	inline double val(int u){return L[u]+R[u];}
	inline bool Cmp(int a,int b){
		return s[a]<s[b]||(s[a]==s[b]&&val(pre[a])<val(pre[b]));
	}
	inline bool eq(int a,int b){
		return s[a]==s[b]&&pre[a]==pre[b];
	}
	cs double alpha=0.8;
	int ins(int &u,int i,double l=0,double r=1e18){
		if(!u){u=i,L[i]=l,R[i]=r,siz[i]=1;return i;}
		if(eq(u,i)){return u;}double M=(l+r)*0.5;int res;
		if(Cmp(u,i)){
			if((res=ins(rc[u],i,M,r))==i){
				++siz[u];if(siz[rc[u]]>siz[u]*alpha)bad=&u;
			}
		}else {
			if((res=ins(lc[u],i,l,M))==i){
				++siz[u];if(siz[lc[u]]>siz[u]*alpha)bad=&u;
			}
		}return res;
	}
	
	int q[N],qn;
	void inorder_dfs(int u){
		if(lc[u])inorder_dfs(lc[u]);q[++qn]=u;
		if(rc[u])inorder_dfs(rc[u]);
	}
	int build(int l,int r,double vl,double vr){
		if(l>r)return 0;int mid=l+r>>1;double M=(vl+vr)*0.5;
		int u=q[mid];L[u]=vl,R[u]=vr;siz[u]=r-l+1;
		lc[u]=build(l,mid-1,vl,M);
		rc[u]=build(mid+1,r,M,vr);
		return u;
	}
	void rebuild(int &k){
		qn=0;inorder_dfs(k);
		k=build(1,qn,L[k],R[k]);
	}
	int Ins(int i){
		bad=nullptr;int t=ins(rt,i);
		if(bad!=nullptr)rebuild(*bad);
		return t;
	}
}

struct data{int l,r,t;};
std::vector<data> rg;
int id[N],rk[N];
void work(){
	scanf("%d",&n);
	for(int re i=2;i<=n;++i)
	scanf("%d",fa+i);
	scanf("%s",s+1);
	for(int re i=1;i<=n;++i){
		pre[i]=bel[fa[i]];
		bel[i]=SGT::Ins(i);
	//	cerr<<"bel : "<<i<<" "<<bel[i]<<"\n";
		id[i]=i;
	}
	std::sort(id+1,id+n+1,[](int i,int j){
		return bel[i]!=bel[j]&&SGT::val(bel[i])<SGT::val(bel[j]);
	});
	for(int re i=1,j;i<=n;i=j){
		j=i;while(bel[id[j]]==bel[id[i]])++j;
		rg.push_back({i,j,bel[id[i]]});
	}
	std::sort(rg.begin(),rg.end(),[](cs data &a,cs data &b){
		return a.t<b.t;
	});
	for(cs auto &t:rg){
		std::sort(id+t.l,id+t.r,[](int i,int j){
			return fa[i]==fa[j]?i<j:rk[fa[i]]<rk[fa[j]];
		});
		for(int re i=t.l;i<t.r;++i)rk[id[i]]=i;
	}
	for(int re i=1;i<=n;++i){
		cout<<id[i]<<" ";
	}
}

void file(){
#ifdef zxyoi
	freopen("tree_SA.in","r",stdin);
#endif
}
signed main(){file();work();return 0;}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值