BZOJ4771 七彩树(主席树)
一道主席树好题
对于每种颜色来说,将同种颜色的节点按照 dfn 排序,每个点的贡献是1,相邻两个点对 LCA 的贡献-1,
只要区间内存在这种颜色,则其子树内的权值和必定为1。染好所有颜色之后询问子树和。 (不知道为什么)
按照深度建立主席树,询问就是区间查询啦
(不知道为什么主席树要开<<7的空间啊,因为这个一直RE。。)
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cmath> #include<stack> #include<queue> #include<set> using namespace std; typedef long long ll; const int maxn = 100010; int n,m,q,f,x,d,test; int c[maxn],b[maxn],p[maxn]; set<int> S[maxn]; set<int>::iterator t1,t2,t3; int h[maxn],size; struct E{ int to,next; }e[maxn*2]; void add(int u,int v){ e[++size].to=v; e[size].next=h[u]; h[u]=size; } int rt[maxn]; int lc[maxn<<7],rc[maxn<<7],val[maxn<<7],cnt; void modify(int &i,int o,int l,int r,int p,int v){ i=++cnt; lc[i]=lc[o],rc[i]=rc[o],val[i]=val[o]+v; if(l==r) return; int mid=(l+r)/2; if(p<=mid) modify(lc[i],lc[i],l,mid,p,v); else modify(rc[i],rc[i],mid+1,r,p,v); } int query(int i,int l,int r,int x,int y){ if(x<=l && r<=y) return val[i]; int mid=(l+r)/2,res=0; if(x<=mid) res+=query(lc[i],l,mid,x,y); if(y>mid) res+=query(rc[i],mid+1,r,x,y); return res; } int dep[maxn],fa[maxn],son[maxn],top[maxn],sz[maxn],dfn[maxn],low[maxn],id[maxn],tot; void dfs1(int u,int par){ sz[u]=1; int maxs=-1; son[u]=0; fa[u]=par; dep[u]=dep[par]+1; for(int i=h[u];i!=-1;i=e[i].next){ int v=e[i].to; if(v==par) continue; dfs1(v,u); sz[u]+=sz[v]; if(sz[v]>maxs){ maxs=sz[v]; son[u]=v; } } } void dfs2(int u,int par){ dfn[u]=++tot; top[u]=par; id[tot]=u; if(!son[u]){ low[u]=tot; return; } dfs2(son[u],par); for(int i=h[u];i!=-1;i=e[i].next){ int v=e[i].to; if(v==fa[u] || v==son[u]) continue; dfs2(v,v); } low[u]=tot; } int LCA(int u,int v){ while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]]) swap(u,v); u=fa[top[u]]; } if(dep[u]>dep[v]) swap(u,v); return u; } bool cmp(int a,int b){ return dep[a]<dep[b]; } ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } int main(){ test=read(); while(test--){ memset(h,-1,sizeof(h)); cnt=0,tot=0,size=0; memset(rt,0,sizeof(rt)); memset(dfn,0,sizeof(dfn)); memset(id,0,sizeof(id)); n=read(),m=read(); for(int i=1;i<=n;i++) c[i]=read(),b[i]=c[i]; sort(b+1,b+1+n); q=unique(b+1,b+1+n)-b-1; for(int i=1;i<=n;i++) c[i]=lower_bound(b+1,b+1+q,c[i])-b; for(int i=2;i<=n;i++) f=read(),add(f,i),add(i,f); dfs1(1,0); dfs2(1,1); for(int i=1;i<=n;i++) p[i]=i; sort(p+1,p+1+n,cmp); for(int i=1;i<=q;i++) S[i].clear(); for(int i=1,j=1;i<=dep[p[n]];i++){ rt[i]=rt[i-1]; while(j<=n && dep[p[j]]==i){ int u=p[j]; S[c[u]].insert(dfn[u]); t1=t2=t3=S[c[u]].find(dfn[u]); t2--,t3++; modify(rt[i],rt[i],1,n,dfn[u],1); if(t1!=S[c[u]].begin()) modify(rt[i],rt[i],1,n,dfn[LCA(u,id[*t2])],-1); // if(t3!=S[c[u]].end()) modify(rt[i],rt[i],1,n,dfn[LCA(u,id[*t3])],-1); // if(t1!=S[c[u]].begin() && t3!=S[c[u]].end()) modify(rt[i],rt[i],1,n,dfn[LCA(id[*t2],id[*t3])],1); // 重点 ++j; } } int ans=0; for(int i=1;i<=m;i++){ x=read()^ans,d=read()^ans; ans=query(rt[min(dep[x]+d,dep[p[n]])],1,n,dfn[x],low[x]); printf("%d\n",ans); } } return 0; }