BZOJ4771 七彩树
BZOJ
不强制在线的话可以树上启发式合并做两个log
然后强制在线的话可以set维护树链的并,然后主席树维护每个深度的答案(下标dfs序)
至于树链的并怎么维护,把同颜色的点放在一个set里,每次查点u的前驱后继,把前驱pre和u的lca--,把后继suc和u的lca--,把suc和pre的lca++,u也要++
然后空间是4log(每个点最多修改4次),大概开70倍的样子
#include<bits/stdc++.h>
using namespace std;
const int _=100005;
int re(){
int x=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
}
int T,n,m,ts,Mx,lca,pre,suc,tot,cnt,ans;
set<int>s[_];
vector<int>vp[_];
set<int>::iterator pos;
int sum[_*70],ls[_*70],rs[_*70];
int c[_],h[_],fa[_],dep[_],son[_],sz[_],top[_],dfn[_],id[_],rt[_];
struct edge{int to,next;}e[_];
void link(int u,int v){e[++cnt]=(edge){v,h[u]};h[u]=cnt;}
void dfs(int u){
sz[u]=1;Mx=max(Mx,dep[u]);vp[dep[u]].push_back(u);
for(int i=h[u];i;i=e[i].next){
int v=e[i].to;dep[v]=dep[u]+1;dfs(v);
sz[u]+=sz[v];if(sz[v]>sz[son[u]])son[u]=v;
}
}
void dfs(int u,int tp){
top[u]=tp;dfn[u]=++ts;id[ts]=u;
if(son[u])dfs(son[u],tp);
for(int i=h[u];i;i=e[i].next){
int v=e[i].to;if(v^son[u])dfs(v,v);
}
}
void qlca(int x,int y){
while(top[x]^top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
lca=dep[x]<dep[y]?x:y;
}
void upd(int&x,int l,int r,int k,int v){
sum[++tot]=sum[x]+v;ls[tot]=ls[x];rs[tot]=rs[x];
x=tot;if(l==r)return;int mid=(l+r)>>1;
if(k<=mid)upd(ls[x],l,mid,k,v);else upd(rs[x],mid+1,r,k,v);
}
int qsum(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return sum[x];int mid=(l+r)>>1,res=0;
if(ql<=mid)res=qsum(ls[x],l,mid,ql,qr);
if(qr>mid)res+=qsum(rs[x],mid+1,r,ql,qr);return res;
}
int main(){
T=re();
while(T--){
n=re(),m=re();Mx=0;tot=0;ts=0;cnt=0;ans=0;
memset(rt,0,sizeof(rt));memset(son,0,sizeof(son));memset(h,0,sizeof(h));
for(int i=1;i<=n;i++)c[i]=re(),s[i].clear(),vp[i].clear();
for(int i=2;i<=n;i++){fa[i]=re();link(fa[i],i);}
dep[1]=1;dfs(1);dfs(1,1);
for(int i=1;i<=Mx;i++){
rt[i]=rt[i-1];
for(int j=0,si=vp[i].size();j<si;j++){
int u=vp[i][j];s[c[u]].insert(dfn[u]);
pos=s[c[u]].find(dfn[u]);
upd(rt[i],1,n,dfn[u],1);
if(pos!=s[c[u]].begin()){
qlca(pre=id[*(--pos)],u);++pos;
upd(rt[i],1,n,dfn[lca],-1);
}
if((++pos)!=s[c[u]].end()){
qlca(suc=id[*pos],u);
upd(rt[i],1,n,dfn[lca],-1);
}
if(pre&&suc){qlca(pre,suc);upd(rt[i],1,n,dfn[lca],1);}
pre=suc=0;
}
}
while(m--){
int u=(re()^ans),d=(re()^ans);
printf("%d
",ans=qsum(rt[min(dep[u]+d,Mx)],1,n,dfn[u],dfn[u]+sz[u]-1));
}
}
return 0;
}