[BZOJ4771]七彩树

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\n",ans=qsum(rt[min(dep[u]+d,Mx)],1,n,dfn[u],dfn[u]+sz[u]-1));
        }
    }
    return 0;
}
posted @ 2018-10-23 22:27  faced  阅读(131)  评论(0编辑  收藏  举报