• 模板【树上点差分】


    PART1(算法思想简介)

    1.实现

    2.时间复杂度

    3.特别优势

    4.适用情况

    5.需要注意的点

    6.函数、变量名的解释+英文

    7.dalao分析

    PART2(算法各种类型(并附上代码))

     1.代码

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<cstring>
    #include<string>
    #include<vector>
    #include<queue>
    #include<iomanip>
    #include<iostream>#include<stack>
    using namespace std;
    #define inf 0x3f3f3f3f
    const int MAXN = 5e4+10;
    const int MAXM = 1e5+10;
    //快读
    inline int read();
    //与边相关
    struct edge
    {
        int u, v, next, w;
    } e[MAXM];
    int p[MAXN], eid;
    inline void InitEdge();
    inline void Insert(int u, int v, int w = 0);
    //lca:先调用LcaPre一次,然后自由调用Lca
    int dep[MAXN];//深度
    int parent[MAXN][20];
    void LcaInit();
    void LcaDfs(int u);
    void LcaPre(int n, int root);//n:结点个数,root:根节点
    int Lca(int x, int y);//x,y:任意两个结点,返回他们的公共祖先结点
    //树上差分
    int sum[MAXN];
    void TreeNodeDifference(int u, int v, int change);
    //求最终结果
    int ans;
    
    void Gmax(int u, int fa);
    //main
    int main()
    {
        //freopen("in.txt","r", stdin);
        //freopen("out.txt","w", stdout);
        ios::sync_with_stdio(false);
        InitEdge();
        int n, k;
        cin >> n >> k;
        int u,v;
        for(int i=1; i<n; i++)
        {
            cin>>u>>v;
            Insert(v, u);
            Insert(u, v);
        }
        LcaPre(n, 1);
        while(k--)
        {
            cin >> u >>v;
            TreeNodeDifference(u, v, 1);
        }
        Gmax(1, -1);
        cout << ans;
        return 0;
    }
    //函数定义
    //快读
    inline int read()//快读板子
    {
        int x=0;
        char c=getchar();
        while(c<'0'||c>'9')
            c=getchar();
        while(c>='0'&&c<='9')
        {
            x=(x<<1)+(x<<3)+c-'0';
            c=getchar();
        }
        return x;
    }
    inline void InitEdge()
    {
        memset(p, -1, sizeof(p));
        eid = 0;
    }
    inline void Insert(int u, int v, int w)
    {
        e[eid].next = p[u];
        e[eid].u = u;
        e[eid].v = v;
        e[eid].w = w;
        p[u] = eid++;
    }
    //lca
    void LcaDfs(int u)
    {
        for(int i = p[u]; i != -1; i = e[i].next)
        {
            if(dep[e[i].v] == -1)
            {
                dep[e[i].v] = dep[u]+1;
                parent[e[i].v][0] = u;
                LcaDfs(e[i].v);
            }
        }
    }
    void LcaPre(int n, int root)
    {
        LcaInit();
        dep[root] = 0;
        LcaDfs(root);
        for(int level = 1; (1 << level) <= n; level++)
            for(int i = 1; i <= n; i++)
            {
                parent[i][level] = parent[parent[i][level-1]][level-1];
            }
    }
    void LcaInit()
    {
        memset(dep, -1, sizeof(dep));
    }
    int Lca(int x, int y)
    {
        int i, j;//之后求出来的i要使用两次,所以用的时候用j代替i
        if(dep[x] < dep[y])//x是更深的那个
        {
            swap(x, y);
        }
        //找到深度不大于dep[x]的最深的2^i
        for(i = 0; (1<<i) <= dep[x]; i++);
        i--;
        //倍增使得dep[x]==dep[y]
        for(j = i; j >= 0; j--)
        {
            if(dep[x] - (1 << j) >= dep[y])
            {
                x = parent[x][j];
            }
        }
        //直接y就是x的最近公共祖先
        if(x == y)
        {
            return x;
        }
        //找到公共祖先
        for(j = i; j >= 0; j--)
        {
            if(parent[x][j] != parent[y][j]) //就是要不相等时才跳,相等时跳那就跳多了而且不行不行
            {
                x = parent[x][j];
                y = parent[y][j];
            }
        }
        return parent[x][0];//因为上面看到相等就不求得跳,所以最终答案是这个!!!
    }
    //树上差分
    void TreeNodeDifference(int u, int v, int change)
    {
        int fa = Lca(u, v);
        sum[u]+=change, sum[v]+=change;
        sum[fa]-=change, sum[parent[fa][0]]-=change;
    }
    //Gmax
    void Gmax(int u, int fa)
    {
        for(int i = p[u]; ~i; i = e[i].next)
        {
            int v = e[i].v;
            if(v == fa)
                continue;
            Gmax(v, u);
            sum[u] += sum[v];
        }
        ans = max(ans, sum[u]);
    }
    View Code

    PART3(算法的延伸应用)

    PART4(对算法深度的理解)

    PART5(与其相关的有趣题目)

     

  • 相关阅读:
    常用SQL Server数据修复命令DBCC一览(转载)
    多线程编程的注意事项
    [转载]Openlayers中使用TileCache加载预切割图片作为基础地图图层
    一个关于工具条可以移动和在四周停留的测试
    SQL Server同名表的判断
    SQL Server 中调整自增字段的当前初始值
    IIS and ASP.NET: The Application Pool
    Server.MapPath(path)
    自动化selenium 鼠标键盘操作& 按键用法
    多层窗口定位&多层框架定位
  • 原文地址:https://www.cnblogs.com/bear-xin/p/15014471.html
Copyright © 2020-2023  润新知