zoukankan      html  css  js  c++  java
  • 树链剖分模板

    代码

    //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
  • 相关阅读:
    FJNU 1151 Fat Brother And Geometry(胖哥与几何)
    FJNU 1157 Fat Brother’s ruozhi magic(胖哥的弱智术)
    FJNU 1159 Fat Brother’s new way(胖哥的新姿势)
    HDU 3549 Flow Problem(最大流)
    HDU 1005 Number Sequence(数列)
    Tickets(基础DP)
    免费馅饼(基础DP)
    Super Jumping! Jumping! Jumping!(基础DP)
    Ignatius and the Princess IV(基础DP)
    Keywords Search(AC自动机)
  • 原文地址:https://www.cnblogs.com/wust-ouyangli/p/5759571.html
Copyright © 2011-2022 走看看