P5537 【XR-3】系统设计
妙妙题。介绍一下单
首先我们观察到树形态不变,那么我们可以快速求出根到每个点的序列值,通过差分也就可以知道任意祖孙点对中间的序列值。
我们需要快速查询一个序列值是否出现过,自然也就想到哈希。
哈希也是支持快速合并的,也就满足序列上的单点修改性质。
那么现在也就变成了查询最大的
显然
首先从左往右找到所有满足
如果
否则,那么答案
加入左子树的哈希值,如果出现过就加入,递归右子树,否则递归左子树。
那么两部分的复杂度是分开的,都是单
注意到这里的哈希值很大,使用 map 会被卡常,建议使用 pb_ds 或者手写哈希表,不会 pb_ds 的右转 如何优雅地使用 pb_ds。
跑得飞快,目前是 rk3,默认
还有不懂的可以看代码,任何问题欢迎与我交流:
#include<bits/stdc++.h>
using namespace std;
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
const int N=5e5+3;
int n,m,q,rt,a[N],fa[N];
vector<int>ve[N];
ull bas=2e6+3,pri=229,cur=0,pw[N],sx[N],tr[N*4];
cc_hash_table<ull,int>mp;
int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
void write(int X)
{
if(X<0){putchar('-');X=~(X-1);}int s[20],o=0;
while(X){s[++o]=X%10;X/=10;}
if(!o)s[++o]=0;while(o)putchar(s[o--]+'0');
putchar('\n');
}
void Dfs(int x,int fa)
{
mp[sx[x]]=x;
for(int i=0,y;i<(ll)ve[x].size();i++)if((y=ve[x][i])!=fa)
sx[y]=sx[x]*bas+i+1+pri,Dfs(y,x);
}
#define ls (p<<1)
#define rs (p<<1|1)
#define mi ((l+r)>>1)
void Up(int p,int len){tr[p]=tr[ls]*pw[len]+tr[rs];}
void Build(int p,int l,int r)
{
if(l==r){tr[p]=a[l]+pri;return;}
Build(ls,l,mi);Build(rs,mi+1,r);Up(p,r-mi);
}
void Upd(int k,int p,int l,int r,int d)
{
if(l==r){tr[p]=d+pri;return;}
k<=mi?Upd(k,ls,l,mi,d):Upd(k,rs,mi+1,r,d);Up(p,r-mi);
}
int Ans(int p,int l,int r)
{
if(l==r)return l;
ull x=cur*pw[mi-l+1]+tr[ls];
if(mp.find(x)==mp.end())return Ans(ls,l,mi);
cur=x;return Ans(rs,mi+1,r);
}
int Ask(int L,int R,int p,int l,int r,int &o)
{
if(L<=l&&r<=R)
{
ull x=cur*pw[r-l+1]+tr[p];
if(mp.find(x)==mp.end()){o=1;return Ans(p,l,r);}
cur=x;return 0;
}
if(L>mi)return Ask(L,R,rs,mi+1,r,o);
if(R<=mi)return Ask(L,R,ls,l,mi,o);
int res=Ask(L,R,ls,l,mi,o);
return o?res:Ask(L,R,rs,mi+1,r,o);
}
int main()
{
n=read();m=read();q=read();pw[0]=1;
for(int i=1;i<N;i++)pw[i]=pw[i-1]*bas;
for(int i=1;i<=n;i++)
{
fa[i]=read();
if(!fa[i])rt=i;
else ve[fa[i]].push_back(i);
}
for(int i=1;i<=m;i++)a[i]=read();
for(int i=1;i<=n;i++)sort(ve[i].begin(),ve[i].end());
Dfs(rt,0);Build(1,1,m);
while(q--)
{
int op,x,l,r;op=read();
if(op==2){l=read();x=read();Upd(l,1,1,m,x);continue;}
x=read();l=read();r=read();cur=sx[x];
int fl=0;Ask(l,r,1,1,m,fl);write(mp[cur]);
}
}