卧槽调了一晚上
想法很简单
用$set$维护不同颜色的树链的并,支持链加和单点查询
具体我们可以差分
于是就是单点加,子树和
考虑深度
我们写一个主席树,第$i$个版本只考虑前$i$层
查询$d + dep[x]$深度的树中$x$子树和即可
调调调
想5min写一晚上
#include<bits/stdc++.h> using namespace std; inline int read() { int x = 0,f = 1;char ch = getchar(); for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f; for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0'; return x * f; } const int maxn = 100010; int n,m,lastans; int c[maxn],id[maxn]; int fa[maxn],dep[maxn],size[maxn],bl[maxn]; int ref[maxn],pos[maxn],last[maxn],dfn; int first[maxn],targ[maxn << 1],nx[maxn << 1],cnt; inline void add(int u,int v){targ[++cnt] = v,nx[cnt] = first[u],first[u] = cnt;} inline void ins(int u,int v){add(u,v),add(v,u);} set<int> cs[maxn]; set<int>::iterator it; inline void dfs1(int u) { size[u]=1;pos[u] = ++dfn;ref[dfn] = u; for(int i=first[u];i;i=nx[i]) { if(targ[i]==fa[u])continue; dep[targ[i]]=dep[u]+1; fa[targ[i]]=u; dfs1(targ[i]); size[u]+=size[targ[i]]; } last[u] = dfn; } inline void dfs2(int u,int idc) { int k=0; bl[u]=idc; for(int i=first[u];i;i=nx[i]) if(dep[targ[i]]>dep[u] && size[targ[i]]>size[k]) k=targ[i]; if(k==0)return; dfs2(k,idc); for(int i=first[u];i;i=nx[i]) if(dep[targ[i]]>dep[u] && k!=targ[i]) dfs2(targ[i],targ[i]); } inline int lca(int x,int y) { while(bl[x] != bl[y]) { if(dep[bl[x]] < dep[bl[y]])swap(x,y); x = fa[bl[x]]; } return dep[x] < dep[y] ? x : y; } int root[maxn],ls[maxn << 6],rs[maxn << 6],val[maxn << 6],ToT; inline void Insert(int &x,int pre,int l,int r,int pos,int v) { x = ++ToT;val[x] = val[pre] + v; if(l == r)return; int mid = (l + r) >> 1; if(pos <= mid)rs[x] = rs[pre],Insert(ls[x],ls[pre],l,mid,pos,v); else ls[x] = ls[pre],Insert(rs[x],rs[pre],mid + 1,r,pos,v); } inline int query(int x,int l,int r,int L,int R) { if(L <= l && r <= R)return val[x]; int mid = (l + r) >> 1,ans = 0; if(L <= mid)ans += query(ls[x],l,mid,L,R); if(R > mid)ans += query(rs[x],mid + 1,r,L,R); return ans; } bool cmp(int u,int v){return dep[u] < dep[v];} int main() { int T = read(); while(T--) { cnt = 0,dfn = 0,ToT = 0,lastans = 0; int p = 1; n = read(),m = read(); for(int i=1;i<=n;i++)c[i] = read(),cs[i].clear(),id[i] = i,first[i] = 0; for(int i=2;i<=n;i++){int u = read();ins(u,i);} dfs1(1);dfs2(1,1);sort(id + 1,id + n + 1,cmp); root[0] = 0;int x,y; for(int i=0;i<n;i++) { if(i)root[i] = root[i - 1]; while(p <= n && dep[id[p]] <= i) { x = 0,y = 0;int pcol = c[id[p]]; it = cs[pcol].lower_bound(pos[id[p]]); if(it != cs[pcol].end())y = ref[*it]; if(it != cs[pcol].begin())x = ref[*--it]; Insert(root[i],root[i],1,n,pos[id[p]],1); if(x)Insert(root[i],root[i],1,n,pos[lca(x,id[p])],-1); if(y)Insert(root[i],root[i],1,n,pos[lca(y,id[p])],-1); if(x && y)Insert(root[i],root[i],1,n,pos[lca(x,y)],1); cs[pcol].insert(pos[id[p]]),++p; } } while(m--) { x = read(),y = read(); x = x ^ lastans,y = min(dep[x] + (y ^ lastans),n - 1); printf("%d " ,lastans = query(root[y],1,n,pos[x],last[x])); } } }
手已经不健康了