zoukankan      html  css  js  c++  java
  • BZOJ 4448 主席树+树链剖分(在线)

    为什么题解都是离线的…… (抄都没法抄
    搞一棵主席树
    1 操作 新树上的当前节点设成1
    2 操作 查max(i-xx-1,0)那棵树上这条路径上有多少个点是1
    让你找经过了多少个点 查的时候用deep 搞出来就好了

    //By SiriusRen
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 444444
    #define mem(x,y) memset(x,y,sizeof(x))
    int n,q,op,xx,yy,zz,first[N],v[N],next[N],tot,root,rt[N],ans;
    int size[N],fa[N],son[N],deep[N],top[N],change[N],back[N],cnt;
    struct Tree{int l,r,num;}tree[N*30];
    void Add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
    void add(int x,int y){Add(x,y),Add(y,x);}
    void dfs(int x){
        size[x]=1;
        for(int i=first[x];~i;i=next[i])if(v[i]!=fa[x]){
            deep[v[i]]=deep[x]+1,fa[v[i]]=x,dfs(v[i]);
            size[x]+=size[v[i]];
            if(size[son[x]]<size[v[i]])son[x]=v[i];
        }
    }
    void dfs2(int x,int tp){
        change[x]=++cnt,back[cnt]=x;top[x]=tp;
        if(son[x])dfs2(son[x],tp);
        for(int i=first[x];~i;i=next[i])
            if(v[i]!=fa[x]&&v[i]!=son[x])dfs2(v[i],v[i]);
    }
    void push_up(int pos){tree[pos].num=tree[tree[pos].l].num+tree[tree[pos].r].num;}
    int build(int l,int r){
        int pos=++cnt;
        if(l==r){return pos;}
        int mid=(l+r)>>1;
        tree[pos].l=build(l,mid),tree[pos].r=build(mid+1,r);
        return pos;
    }
    int insert(int o,int l,int r,int num){
        int pos=++cnt;tree[pos]=tree[o];
        if(l==r){tree[pos].num=1;return pos;}
        int mid=(l+r)>>1;
        if(mid>=num)tree[pos].l=insert(tree[o].l,l,mid,num);
        else tree[pos].r=insert(tree[o].r,mid+1,r,num);
        push_up(pos);return pos;
    }
    int query(int o,int l,int r,int L,int R){
        if(l>=L&&r<=R)return tree[o].num;
        int mid=(l+r)>>1; 
        if(mid<L)return query(tree[o].r,mid+1,r,L,R);
        else if(mid>=R)return query(tree[o].l,l,mid,L,R);
        else return query(tree[o].l,l,mid,L,R)+query(tree[o].r,mid+1,r,L,R);
    }
    int find(int x,int y,int wei){
        int fx=top[x],fy=top[y],temp=0;
        while(fx!=fy){
            if(deep[fx]<deep[fy])swap(x,y),swap(fx,fy);
            temp+=query(rt[wei],1,n,change[fx],change[x]),ans+=deep[x]-deep[fx]+1;
            x=fa[fx],fx=top[x];
        }
        if(deep[x]<deep[y])swap(x,y);
        ans+=deep[x]-deep[y]+1;
        return temp+query(rt[wei],1,n,change[y],change[x]);
    }
    int main(){
        mem(first,-1);scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&fa[i]);
            if(!fa[i])root=i;else add(i,fa[i]);
        }
        dfs(root),dfs2(root,root),cnt=0,rt[0]=build(1,n);
        scanf("%d",&q);
        for(int i=1;i<=q;i++){
            scanf("%d",&op);
            if(op==1){
                rt[i]=rt[i-1],ans=0;
                scanf("%d%d%d",&xx,&yy,&zz);
                zz=max(i-zz-1,0);
                printf("%d %d
    ",ans,find(xx,yy,zz));
            }
            else scanf("%d",&xx),rt[i]=insert(rt[i-1],1,n,change[xx]);
        }
    }

    这里写图片描述

  • 相关阅读:
    力扣算法:组合总和IV
    力扣算法:组合总和III
    逻辑回归(Logistic Regression)学习笔记
    力扣算法:组合总和II
    力扣算法:组合总和
    寒假作业(五)
    寒假作业(四)
    寒假作业(三)
    寒假作业(二)
    寒假学习(一)
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532105.html
Copyright © 2011-2022 走看看