• 树链剖分(剖链模板)


    1.前向星型模板

    /*
    重儿子:siz[u]为v的子节点中siz值最大的,那么u就是v的重儿子。
    轻儿子:v的其它子节点。
    重边:点v与其重儿子的连边。
    轻边:点v与其轻儿子的连边。
    重链:由重边连成的路径。
    轻链:轻边。
    */const int MAXN = 50000+10;
    struct node
    {
        int to, next;
        node(){
        }
        node(int to, int next) : to(to), next(next){
        }
    }edge[2*MAXN];
    int head[MAXN], alledge;
    void init()
    {
        memset(head, 0xff, sizeof(head));
        alledge = 0;
    }
    void addedge(int x, int y)
    {
        edge[alledge] = node(y, head[x]);
        head[x] = alledge++;
        edge[alledge] = node(x, head[y]);
        head[y] = alledge++;
    }
    int a[MAXN];//点权值
    int siz[MAXN];//siz[v]表示以v为根的子树的节点数(包含自身结点)
    int dep[MAXN];//dep[v]表示v的深度(根深度为1)
    int fa[MAXN];//fa[v]表示v的父亲
    int son[MAXN];//son[v]表示与v在同一重链上的v的儿子节点(姑且称为重儿子)
    int top[MAXN];//top[v]表示v所在的链的顶端节点
    int w[MAXN];//w[v]表示v与其父亲节点的连边(姑且称为v的父边)在线段树中的位置
    int totw;
    void init_treelist()
    {
        memset(son, 0xff, sizeof(son));// son[v]为 -1 表示重儿子不存在 
        memset(top, 0xff, sizeof(top));
        totw = 0; 
    }
    void dfs_1(int id, int pr, int deep)//求 fa、dep、siz、son、top
    {
        fa[id] = pr; dep[id] = deep; siz[id] = 1;
        int s = -1, ii = -1;
        for(int i = head[id]; ~i; i = edge[i].next)
        {
            int to = edge[i].to;
            if(to == pr) continue;
            dfs_1(to, id, deep+1);
            siz[id] += siz[to];
            if(siz[to] > s)
            {
                s = siz[to];
                ii = to;
            }
        }
        son[id] = ii;
    }
    void dfs_2(int id, int pr)//求 w
    {
         w[id] = ++totw;
         if(top[id]==-1) top[id] = id;
         if(~son[id])
         {
             top[son[id]] = top[id];
             dfs_2(son[id], id);
         }
        for(int i = head[id]; ~i; i = edge[i].next)
        {
            int to = edge[i].to;
             if(to == pr) continue;
             if(to == son[id]) continue;
             dfs_2(to, id);
        }
    }
    void update(int x, int y, int k)
    {
        int fx = top[x], fy = top[y];
        while(fx != fy)
        {
            if(dep[fx] < dep[fy])
            {
                swap(fx, fy);
                swap(x, y);
            }
            //update(1, 1, n, w[fx], w[x], k); 线段树更新 
            x = fa[fx]; fx = top[x];
        }
        if(dep[x] < dep[y])
        {
            swap(x, y);
        }
        //update(1, 1, n, w[y], w[x], k); 线段树更新
    }
    int main (void)
    {
        /*
        建图 
        */ 
        dfs_1(1, -1, 1);
        dfs_2(1, -1); 
    } 

    顺附 codefroces 343D -  Water Tree AC代码

    /*
    重儿子:siz[u]为v的子节点中siz值最大的,那么u就是v的重儿子。
    轻儿子:v的其它子节点。
    重边:点v与其重儿子的连边。
    轻边:点v与其轻儿子的连边。
    重链:由重边连成的路径。
    轻链:轻边。
    */
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int MAXN = 500000+10;
    int n; 
    struct node
    {
        int to, next;
        node(){
        }
        node(int to, int next) : to(to), next(next){
        }
    }edge[2*MAXN];
    int head[MAXN], alledge;
    void init()
    {
        memset(head, 0xff, sizeof(head));
        alledge = 0;
    }
    void addedge(int x, int y)
    {
        edge[alledge] = node(y, head[x]);
        head[x] = alledge++;
        edge[alledge] = node(x, head[y]);
        head[y] = alledge++;
    }
    int siz[MAXN];//siz[v]表示以v为根的子树的节点数(包含自身结点)
    int dep[MAXN];//dep[v]表示v的深度(根深度为1)
    int fa[MAXN];//fa[v]表示v的父亲
    int son[MAXN];//son[v]表示与v在同一重链上的v的儿子节点(姑且称为重儿子)
    int top[MAXN];//top[v]表示v所在的链的顶端节点
    int w[MAXN];//w[v]表示v与其父亲节点的连边(姑且称为v的父边)在线段树中的位置
    int End[MAXN], END;
    int totw;
    void init_treelist()
    {
        memset(son, 0xff, sizeof(son));// son[v]为 -1 表示重儿子不存在
        memset(top, 0xff, sizeof(top));
        totw = 0;
    }
    void dfs_1(int id, int pr, int deep)//求 fa、dep、siz、son、top
    {
        fa[id] = pr; dep[id] = deep; siz[id] = 1;
        int s = -1, ii = -1;
        for(int i = head[id]; ~i; i = edge[i].next)
        {
            int to = edge[i].to;
            if(to == pr) continue;
            dfs_1(to, id, deep+1);
            siz[id] += siz[to];
            if(siz[to] > s)
            {
                s = siz[to];
                ii = to;
            }
        }
        son[id] = ii;
    }
    void dfs_2(int id, int pr)//求 w
    {
         w[id] = ++totw;
         END = id;
         if(top[id]==-1) top[id] = id;
         if(~son[id])
         {
             top[son[id]] = top[id];
             dfs_2(son[id], id);
         }
        for(int i = head[id]; ~i; i = edge[i].next)
        {
            int to = edge[i].to;
             if(to == pr) continue;
             if(to == son[id]) continue;
             dfs_2(to, id);
        }
        End[id] = END;
    }
    
    struct treenode
    {
        int v;
        int flag;
    }tree[MAXN<<2];
    void bulid_tree()
    {
        memset(tree, 0x00, sizeof(tree));
    }
    void push_down(int id)
    {
        tree[id<<1].flag = tree[id].flag;
        tree[(id<<1)|1].flag = tree[id].flag;
        tree[id].flag = 0;
    }
    void update(int id, int l, int r, int left, int right, int k)
    {
        if(l==left && r==right)
        {
            if(k==0) tree[id].flag = -1;
            if(k==1) tree[id].flag = 1;
            if(l==r) tree[id].v = k;
            return ;
        }
        int mid = l+r>>1;
        if( tree[id].flag ) push_down(id);
        if(right <= mid)
        {
            update(id<<1, l, mid, left, right, k);
        }
        else if(left > mid)
        {
            update((id<<1)|1, mid+1, r, left, right, k);
        }
        else
        {
            update(id<<1, l, mid, left, mid, k);
            update((id<<1)|1, mid+1, r, mid+1, right, k);
        }
    }
    int query(int id, int l, int r, int index)
    {
        if(tree[id].flag == -1) return 0;
        if(tree[id].flag == 1) return 1;
        if(l==r&& r==index) return tree[id].v;
        int mid = l+r>>1;
        if(index <= mid) return query(id<<1, l, mid, index);
        return query((id<<1)|1, mid+1, r, index);
    }
    void update(int x, int y, int k)
    {
        int fx = top[x], fy = top[y];
        while(fx != fy)
        {
            if(dep[fx] < dep[fy])
            {
                swap(fx, fy);
                swap(x, y);
            }
            update(1, 1, n, w[fx], w[x], k);
            x = fa[fx]; fx = top[x];
        }
        if(dep[x] < dep[y])
        {
            swap(x, y);
        }
        update(1, 1, n, w[y], w[x], k);
    }
    int main (void)
    {
        ios::sync_with_stdio(false);
        init();
        init_treelist();
        cin >> n;
        for(int i = 1; i < n; ++i)
        {
            int x, y;
            cin >> x >> y;
            addedge(x, y);
        }
        dfs_1(1, -1, 1);
        dfs_2(1, -1);
        int q; cin >> q;
        while(q--)
        {
            int c, x; cin >> c >> x;
            switch( c )
            {
                case 1: update(1, 1, n, w[x], w[End[x]], 1); break;
                case 2: update(1, x, 0); break;
                default : cout << query(1, 1, n, w[x]) << endl; break;
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    webpack学习笔记五
    webpack的学习使用四
    判断数组B是否为数组A的子集
    html5标签知多少
    图代文时隐藏文字的兼容实现
    负margin的移位参考线
    font-size 兼容问题
    IE6读取不到样式文件bug
    一个重构眼中的“项目管理”
    唯物 VS 唯心
  • 原文地址:https://www.cnblogs.com/lkcc/p/7701634.html
Copyright © 2020-2023  润新知