11.02 长者题解

11.02 校内模拟赛 题 长者题解和自身体会

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e5+10,P=131,P2=13331,MOD=1e9+7;
char a[N],b[5];
int m,po2[N],rt[N],tot,ans[N];
ull po[N];
struct node {
	ull sumv; int cnt,lc,rc,sumv2;
} T[N*22];
inline void pushup(int p) {
	T[p].sumv=T[T[p].lc].sumv*po[T[T[p].rc].cnt]+T[T[p].rc].sumv;  //求出字符的hash值 
	T[p].sumv2=(1ll*T[T[p].lc].sumv2*po2[T[T[p].rc].cnt]+T[T[p].rc].sumv2)%MOD; //求出hash值 
	T[p].cnt=T[T[p].lc].cnt+T[T[p].rc].cnt; //字符串长度  
}
int build(int l,int r) {
	int p=++tot;  
	if (l==r) {
		T[p].sumv=a[l]-'a'; T[p].sumv2=a[l]-'a'; //这里编号1的主席树上根节点存的是(序号) 
		T[p].cnt=1; return p; } //这里略微不懂。。。尬  即cnt意义是字符串长度 
 	int mid=(l+r)>>1; T[p].lc=build(l,mid); //正常动态开点建树 
	T[p].rc=build(mid+1,r); pushup(p); return p; }  //建树返回树的编号。。注意这里要上放 
int insert(int la,int l,int r,int x,int v) {
	int p=++tot; T[p]=T[la];  //继续动态开点,并且选取模板(我自己的叫法),因为这里是在原字符串基础上搞所以继承他的root 
	if (l==r) {    //如果已经开到了叶节点         
		T[p].sumv=v; T[p].sumv2=v; return p; }   //那么就记录两个hash值 
	int mid=(l+r)>>1;  
	if (x<=mid) T[p].lc=insert(T[la].lc,l,mid,x,v);  //按照动态开点思路,继续向下开开开 
	else T[p].rc=insert(T[la].rc,mid+1,r,x,v);
	pushup(p); return p; } //注意这里 的上放 
bool query(int x,int y,int l,int r) {      
	if (l==r) return T[x].sumv<T[y].sumv;    //因为不用MOd所以可以比较大小、、、 
	int mid=(l+r)>>1;  
	if (T[T[x].lc].sumv!=T[T[y].lc].sumv||T[T[x].lc].sumv2!=T[T[y].lc].sumv2) return query(T[x].lc,T[y].lc,l,mid);
	else return query(T[x].rc,T[y].rc,mid+1,r);}
inline bool cmp(int x,int y) {
	if (T[rt[x]].sumv==T[rt[y]].sumv&&T[rt[x]].sumv2==T[rt[y]].sumv2) return x<y; //判定的是当两个字符串相同时,要判定位置大小 
	return query(rt[x],rt[y],1,m);} //不然判定的是字符串大小 
int main() {
	int n;
	scanf("%d%d",&n,&m);
	scanf("%s",a+1);
	po[0]=1; po2[0]=1;
	for (register int i=1; i<=m; ++i) po[i]=po[i-1]*P,po2[i]=1ll*po2[i-1]*P2%MOD;//双哈希, 一个mod,一个不MOd的原因是因为(p1==131,p2==13331) 
	rt[1]=build(1,m);
	for (register int i=2; i<=n; ++i) {
		int la,pos; scanf("%d%d%s",&la,&pos,b+1); 
		rt[i]=insert(rt[la],1,m,pos,b[1]-'a'); //这里犯错了,,数据保证了处理到la时 其rt[a]一定已经处理过了。依据(Pi<=i) 插入到主席树中的数据也是字符序号 
	}
	for (register int i=1; i<=n; ++i) ans[i]=i; 
	sort(ans+1,ans+n+1,cmp);
	for (register int i=1; i<=n; ++i) printf("%d ",ans[i]); //剩下的就是书答案了 
	return 0; //总结这篇程序。。呵呵,直接用hash值表示字符串大小,,你都比我 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值