• 树链剖分模板


    代码

    //input(输入是先输N,再输N-1条边带权),调用dfs和Div,然后建线段树,更新每个点的值
    //Find用于找两个点之间的最大值或其他,Update用于单点更新,如果成段更新于Find写得类似
    #define tu nod[u]
    #define tv nod[v]
    #define e tree[id]
    #define lson tree[id*2]
    #define rson tree[id*2+1]
    int N;
    struct node{ int top,fa,deep,s,p,fp,son; };
    struct edge
    {
        int u,v,c;
        edge(int u=0,int v=0,int c=0):u(u),v(v),c(c){}
    }E[maxn];
    struct Tree{ int le,ri,v; };
    struct DivTree
    {
        int pid;
        vector<int> G[maxn];
        node nod[maxn];
        Tree tree[4*maxn];
        void init()
        {
            pid=0;
            for(int i=0;i<maxn;i++) G[i].clear(),nod[i].son=-1; //初始化
        }
        void dfs(int u,int fa,int deep)
        {
            tu.fa=fa,tu.deep=deep,tu.s=1;  //保存父节点,深度,大小为1
            int Size=G[u].size();
            for(int i=0;i<Size;i++)
            {
                int v=G[u][i];
                if(v==fa) continue;  //父亲不管
                dfs(v,u,deep+1);
                tu.s+=tv.s;  //加上大小
                if(tu.son==-1||tv.s>nod[tu.son].s) tu.son=v; //找重链所指向的点
            }
        }
        void Div(int u,int top)
        {
            tu.top=top;  //重链顶点
            tu.p=++pid;  //重新编号
            nod[tu.p].fp=u;
            if(tu.son!=-1) Div(tu.son,top); //有重链继续往下找
            else return;
            int Size=G[u].size();
            for(int i=0;i<Size;i++)
            {
                int v=G[u][i];
                if(v==tu.fa||v==tu.son) continue;
                Div(v,v); //新的重链
            }
        }
        void pushup(int id){ e.v=max(lson.v,rson.v); }
        void Build_tree(int id,int le,int ri)
        {
            e.le=le,e.ri=ri,e.v=0;
            if(le==ri) return;
            int mid=(le+ri)/2;
            Build_tree(id*2,le,mid);
            Build_tree(id*2+1,mid+1,ri);
        }
        void Update(int id,int k,int v)
        {
            int le=e.le,ri=e.ri;
            if(le==ri){ e.v=v; return; }
            int mid=(le+ri)/2;
            if(k<=mid) Update(id*2,k,v);
            else Update(id*2+1,k,v);
            pushup(id);
        }
        int Query(int id,int x,int y)
        {
            int le=e.le,ri=e.ri;
            if(x<=le&&ri<=y) return e.v;
            int mid=(le+ri)/2;
            int ret=0;
            if(x<=mid) ret=max(ret,Query(id*2,x,y));
            if(y>mid)  ret=max(ret,Query(id*2+1,x,y));
            return ret;
        }
        int Find(int u,int v)
        {
            int f1=tu.top,f2=tv.top;
            int ret=0;
            while(f1!=f2) //不在同一条链上
            {
                if(nod[f1].deep<nod[f2].deep)  //总是让u是深度大的点
                {
                    swap(f1,f2);
                    swap(u,v);
                }
                ret=max(ret,Query(1,nod[f1].p,tu.p));  //查询这条链
                u=nod[f1].fa; f1=tu.top;   //跳到父节点去
            }
            if(u==v) return ret;  //相同
            if(tu.deep>tv.deep) swap(u,v);
            ret=max(ret,Query(1,nod[tu.son].p,tv.p)); //查询同一条链上的这段区间
            return ret;
        }
        void input() //输入是输入一个N,再输入N-1条带权边
        {
            scanf("%d",&N);
            init();
            for(int i=1;i<N;i++)
            {
                int u,v,c;
                scanf("%d%d%d",&u,&v,&c);
                E[i]=edge(u,v,c);   //
                G[u].push_back(v);
                G[v].push_back(u);
            }
            dfs(1,0,0);
            Div(1,1);
            Build_tree(1,1,pid); //建树
            for(int i=1;i<N;i++)
            {
                edge& t=E[i];
                int& u=t.u;
                int& v=t.v;
                if(tu.deep>tv.deep) swap(u,v);
                Update(1,tv.p,t.c);   //修改边权,偏向v
            }
        }
    };
    View Code
  • 相关阅读:
    集合-ConcurrentSkipListMap 源码解析
    集合-跳表SkipList
    集合-ConcurrentHashMap 源码解析
    >>《移动设计模式大观.pdf》
    >>《《iOS 人机界面准则》中文版.pdf》
    >《Web导航设计.pdf》
    >>《设计心理学名着-2 情感化设计 诺曼着.pdf》
    自制网页(html+css+js+jQuery)
    仿写抽屉新热榜 (html+css)
    运动员喝饮料问题
  • 原文地址:https://www.cnblogs.com/wust-ouyangli/p/5759571.html
Copyright © 2020-2023  润新知