zoukankan      html  css  js  c++  java
  • [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
    ",ans=qsum(rt[min(dep[u]+d,Mx)],1,n,dfn[u],dfn[u]+sz[u]-1));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    CAAnimation动画相关文章
    [源代码]List的增加与删除
    [原创]c# 类中 Collection 字段初始化的特殊之处
    c# 多数值区间判断是否有重叠
    将M个客服随机分配给N个客户
    c# IList.ToList()后更改元素值会不会影响原列表的值
    java单元测试之Mock静态方法
    java的Spring学习2- junit和mock
    java mybatis学习二
    java8 方法引用与lambda
  • 原文地址:https://www.cnblogs.com/sdzwyq/p/9839868.html
Copyright © 2011-2022 走看看