[luogu5537]系统设计
考虑哈希,令$h[x]$表示根到$x$路径的哈希值,那么有$h[x]+hash(l,r)=h[ans]$
考虑用线段树维护$a_{i}$的区间哈希值,并用map去找到对应的$ans$
但还有一个问题,就是并不一定都能走完,可以在线段树上二分走到哪里,时间复杂度为$o(n\log^{2}n)$
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 500005 4 #define L (k<<1) 5 #define R (L+1) 6 #define mid (l+r>>1) 7 #define base 500007 8 #define mod 998244353 9 vector<int>v[N]; 10 map<int,int>mat; 11 int rt,n,m,q,p,x,y,z,h[N],mi[N],f[N<<2]; 12 void update(int k,int l,int r,int x,int y){ 13 if (l==r){ 14 f[k]=y; 15 return; 16 } 17 if (x<=mid)update(L,l,mid,x,y); 18 else update(R,mid+1,r,x,y); 19 f[k]=(1LL*f[L]*mi[r-mid]+f[R])%mod; 20 } 21 int query(int k,int l,int r,int x,int y){ 22 if ((l>y)||(x>r))return 0; 23 if ((x<=l)&&(r<=y))return f[k]; 24 int ll=max(mid+1,x),rr=min(r,y),len=max(rr-ll+1,0); 25 return (1LL*query(L,l,mid,x,y)*mi[len]+query(R,mid+1,r,x,y))%mod; 26 } 27 int query(int k,int l,int r,int x,int y,int z){ 28 if ((l>y)||(x>r)||(!mat[z]))return 0; 29 if (l==r)return mat[z]; 30 int ll=max(l,x),rr=min(mid,y),len=max(rr-ll+1,0); 31 int ans=query(R,mid+1,r,x,y,(1LL*z*mi[len]+query(1,1,n,ll,rr))%mod); 32 if (ans)return ans; 33 return query(L,l,mid,x,y,z); 34 } 35 void dfs(int k,int s){ 36 h[k]=s; 37 mat[s]=k; 38 for(int i=0;i<v[k].size();i++)dfs(v[k][i],(1LL*s*base+i+1)%mod); 39 } 40 int main(){ 41 mi[0]=1; 42 for(int i=1;i<N-4;i++)mi[i]=1LL*mi[i-1]*base%mod; 43 scanf("%d%d%d",&n,&m,&q); 44 for(int i=1;i<=n;i++){ 45 scanf("%d",&x); 46 if (!x)rt=i; 47 else v[x].push_back(i); 48 } 49 dfs(rt,0); 50 for(int i=1;i<=m;i++){ 51 scanf("%d",&x); 52 update(1,1,m,i,x); 53 } 54 for(int i=1;i<=q;i++){ 55 scanf("%d%d%d",&p,&x,&y); 56 if (p==2)update(1,1,m,x,y); 57 else{ 58 scanf("%d",&z); 59 int hh=(1LL*h[x]*mi[z-y+1]+query(1,1,m,y,z))%mod; 60 if (mat[hh])printf("%d\n",mat[hh]); 61 else printf("%d\n",query(1,1,m,y,z,h[x])); 62 } 63 } 64 }