P5537 【XR-3】系统设计
【XR-3】系统设计
题目描述
小 X 需要你设计一个系统。
这个系统首先需要输入一棵
操作分两种:
1 x l r
表示设定起点为有根树的节点 ,接下来依次遍历 。当遍历到 时,从当前节点走向它的编号第 小的儿子。如果某一时刻当前节点的儿子个数小于 ,或者已经遍历完 ,则在这个点停住,并输出这个点的编号,同时停止遍历。2 t k
表示将序列中第 个数 修改为 。
输入格式
第一行
第二行
第三行
接下来
数据范围:
。 。- 对于操作
,保证 , 。 - 对于操作
,保证 , 。
输出格式
对于每个操作
用hash[x]来维护从rt走到x的前缀。
(维护的是一个表示路径的数字序列,表示从rt走到x每次走的是编号第几大的儿子)
形式化的:一段路径{1,5,8,3}表示从rt到x这条路径是访问了rt的第1大儿子(记为x1),x1的第5大儿子x2.....
这样,我们处理每次询问时,我们认为[l,r]构成一个序列。
只需要二分出最大的ans,使得从x开始的访问序列[l,ans]合法
将从rt到某个点mid的路径 rt->mid 转化为从x到mid的路径 __x->mid__的方法:
由于我们存的是路径hash,只需要在询问时差分就好了。
那么现在我们面临的问题就只有储存一段区间上路径的hash了:
由于我不想写线段树
由于我想复习一下树状数组(确信)
所以我很自然的想到了树状数组
code:
#include<bits/stdc++.h> const int N=5e5+5; const int P=131313131; using namespace std; typedef unsigned long long ull; int n,m,rt,q; int dep[N],fa[N],a[N]; ull hsh[N],p[N],t[N],p2[N]; unordered_map<ull,int> Map; vector<int> G[N]; void dfs(int u,int f) { int tot=0; dep[u]=dep[f]+1; for(int v:G[u]) { tot++; hsh[v]=hsh[u]*P+tot; Map[hsh[v]]=v; dfs(v,u); } } int lb(int x) { return -x&x; } void add(int x,ull y) { for(int i=x;i<=n;i+=lb(i)) { t[i]+=y; y*=p[lb(i)]; } } ull query_pos(int x) { ull y=1,res=0; for(int i=x;i;i-=lb(i)) { res+=t[i]*y; y*=p[lb(i)]; } return res; } ull query_range(int l,int r) { return query_pos(r)-query_pos(l-1)*p[r-l+1]; } bool check(int x,int L,int mid) { ull ask=hsh[x]*p[mid-L+1]+query_range(L,mid); return Map.find(ask)!=Map.end(); } void work() { cin>>n>>m>>q; for(int i=1;i<=n;i++) { scanf("%d",&fa[i]); if(!fa[i])rt=i; else { G[fa[i]].push_back(i); } } p[0]=1; for(int i=1;i<=m;i++) { p[i]=p[i-1]*P; } for(int i=1;i<=n;i++) { sort(G[i].begin(),G[i].end()); } dfs(rt,0); for(int i=1;i<=m;i++) { scanf("%d",&a[i]); add(i,a[i]); } for(int i=1,opt,l,r,x;i<=q;i++) { scanf("%d",&opt); if(opt==1) { scanf("%d%d%d",&x,&l,&r); int L=l;l--; while(l<r) { int mid=l+r+1>>1; check(x,L,mid)? l=mid : r=mid-1; } ull val=hsh[x]*p[l-L+1]+query_range(L,l); int ans=Map[val]; printf("%d\n",ans? ans:x); } else { scanf("%d%d",&l,&x); add(l,x-a[l]); a[l]=x; } } } int main() { freopen("P5537.in","r",stdin);freopen("P5537.out","w",stdout); work(); }