P5537 【XR-3】系统设计
【XR-3】系统设计
题目描述
小 X 需要你设计一个系统。
这个系统首先需要输入一棵 \(n\) 个点的有根树和一个长度为 \(m\) 的序列 \(a\),接下来需要实现 \(q\) 个操作。
操作分两种:
1 x l r表示设定起点为有根树的节点 \(x\),接下来依次遍历 \(l \sim r\)。当遍历到 \(i\) 时,从当前节点走向它的编号第 \(a_i\) 小的儿子。如果某一时刻当前节点的儿子个数小于 \(a_i\),或者已经遍历完 \(l \sim r\),则在这个点停住,并输出这个点的编号,同时停止遍历。2 t k表示将序列中第 \(t\) 个数 \(a_t\) 修改为 \(k\)。
输入格式
第一行 \(3\) 个正整数 \(n,m,q\),分别表示树的点数、序列的长度和操作个数。
第二行 \(n\) 个整数 \(f_{1 \dots n}\),其中 \(f_i\) 表示点 \(i\) 在树中的父亲节点编号,特别地,设根节点为 \(rt\),则 \(f_{rt} = 0\)。
第三行 \(m\) 个正整数 \(a_{1 \dots m}\),表示序列 \(a\)。
接下来 \(q\) 行,每行描述一个操作。
数据范围:
- \(1 \le n,m,q \le 5 \times 10 ^ 5\)。
- \(1 \le a_i \le n\)。
- 对于操作 \(1\),保证 \(1 \le x \le n\),\(1 \le l \le r \le m\)。
- 对于操作 \(2\),保证 \(1 \le t \le m\),\(1 \le k \le n\)。
输出格式
对于每个操作 \(1\),一行一个正整数,表示答案。
用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();
}

浙公网安备 33010602011771号