• 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;
    }

      

  • 相关阅读:
    第十四回 基础才是重中之重~委托实例的几种定义方式(规规矩矩method,逻辑简单delegate,层次清晰lambda)
    第十五回 基础才是重中之重~老赵写的CodeTimer是代码性能测试的利器
    第十一回 基础才是重中之重~Conditional特性使代码根据条件在debug或者release模式中执行
    第十二回 基础才是重中之重~.net中的显式事务与隐式事务
    IE绝对定位元素神秘消失或被遮挡的解决方法
    图片按钮样式隐藏文字的
    javascript 保留小数
    Javascript兼容性问题小结(容易导致浏览器不同,又不容易察觉的)
    SQL 随机选取10条数据
    动态添加类和元素样式属性(style and className)
  • 原文地址:https://www.cnblogs.com/tuchen/p/10340207.html
Copyright © 2020-2023  润新知