• Housewife Wind


    【原题链接】

    【题意说明】

    给一个树,边之间有权值,然后两种操作,第一种:求任意两点的权值和,第二,修改树上某点的权值

    【问题分析】

    本题就是对树进行单点更新和区域查询,显然可以使用树链剖分来完成。应该是一个比较基础的树链剖分题,注意每当区域查询后,要修改当前所有在的位置。

    【参考代码】

    #include <cstdio>

    #include <cstring>

    #include <algorithm>

    using namespace std;

    #define fr(i) edge[i].from

    #define to(i) edge[i].to

    #define nt(i) edge[i].next

    #define vl(i) edge[i].value

    #define hd(i) node[i].head

    #define fa(i) node[i].father

    #define dp(i) node[i].deep

    #define sz(i) node[i].size

    #define sn(i) node[i].son

    #define cd(i) node[i].code

    #define tp(i) node[i].top

    #define lt(i) tree[i].left

    #define rt(i) tree[i].right

    #define vt(i) tree[i].value

    #define lson k<<1

    #define rson k<<1|1

    const int maxN=100010;

    struct Tree{

             int left, right, value;

    }tree[maxN<<2];

    struct Edge{

             int from, to, next, value;

    }edge[maxN<<1];

    struct Node{

             int head, father, deep, size, son, code, top;

    }node[maxN];

    int n, q, s, total=0, cnt=0;

    void addedge(int, int, int);

    void build(int, int, int);

    void update(int, int, int);

    int query(int, int, int);

    int solve(int, int);

    void work();

    void dfs1(int, int);

    void dfs2(int, int);

    int main(){

             work();

             return 0;

    }

    void work(){

             memset(node, 0, sizeof(node));

             memset(edge, 0, sizeof(edge));

             memset(tree, 0, sizeof(tree));

             scanf("%d%d%d", &n, &q, &s);

             for(int i=0; i<n-1; i++){

                       int x, y, w;

                       scanf("%d%d%d", &x, &y, &w);

                       addedge(x, y, w);

                       addedge(y, x, w);

             }

             dfs1(1, 1);

             dfs2(1, 1);

             build(1, 1, total);

             for(int i=1; i<cnt; i+=2){

                       int u=fr(i), v=to(i);

                       if(dp(u)<dp(v)) swap(u, v);

                       update(1, cd(u), vl(i));

             }

             for(int i=0; i<q; i++){

                       int t, u, v, x;

                       scanf("%d%d", &t, &u);

                       if(t){

                                scanf("%d", &x);

                                v=to(u-1<<1|1); u=fr(u-1<<1|1);

                                if(dp(u)<dp(v)) swap(u, v);

                                update(1, cd(u), x);

                       }else{

                                printf("%d ", solve(s, u));

                                s=u;

                       }

             }

    }

    void addedge(int x, int y, int w){

             fr(++cnt)=x; to(cnt)=y; vl(cnt)=w;

             nt(cnt)=hd(x); hd(x)=cnt;

    }

    void dfs1(int u, int k){

             sz(u)=1; dp(u)=k;

             for(int i=hd(u); i; i=nt(i)){

                       if(sz(to(i))) continue;

                       fa(to(i))=u;

                       dfs1(to(i), k+1);

                       sz(u)+=sz(to(i));

                       if(sz(sn(u))<sz(to(i))) sn(u)=to(i);

             }       

    }

    void dfs2(int u, int _tp){

             cd(u)=++total; tp(u)=_tp;

             if(sn(u)) dfs2(sn(u), _tp);

             for(int i=hd(u); i; i=nt(i))

                       if(!cd(to(i))) dfs2(to(i), to(i));

    }

    void build(int k, int l, int r){

             lt(k)=l; rt(k)=r;

             if(l==r) return;

             int mid=(l+r)>>1;

             build(lson, l, mid);

             if(mid<r) build(rson, mid+1, r);

    }

    void update(int k, int x, int v){

             if(lt(k)==rt(k)){

                       vt(k)=v;

                       return;

             }

             if(x<=rt(lson)) update(lson, x, v);

             if(x>=lt(rson)) update(rson, x, v);

             vt(k)=vt(lson)+vt(rson);

    }

    int solve(int u, int v){

             int f1=tp(u), f2=tp(v), ans=0;

             while(f1!=f2){

                       if(dp(f1)<dp(f2)){

                                swap(u, v);

                                swap(f1, f2);

                       }

                       ans+=query(1, cd(f1), cd(u));

                       u=fa(f1); f1=tp(u);

             }

             if(u==v) return ans;

             if(dp(u)<dp(v))  swap(u, v);

             return ans+=query(1, cd(sn(v)), cd(u));

    }

    int query(int k, int l, int r){

             if(l<=lt(k)&&r>=rt(k)) return vt(k);

             if(r<=rt(lson)) return query(lson, l, r);

             if(l>=lt(rson)) return query(rson, l, r);

             return query(lson, l, rt(lson))+query(rson, lt(rson), r);

    }

     

  • 相关阅读:
    SQL Server索引进阶:第九级,读懂执行计划
    SQL Server索引进阶:第八级,唯一索引
    SQL Server索引进阶:第七级,过滤的索引
    SQL Server索引进阶:第六级,标签
    SQL Server索引进阶:第五级,包含列
    SQL Server索引进阶:第四级,页和区
    SQL Server索引进阶:第三级,聚集索引
    SQL Server索引进阶:第二级,深入非聚集索引
    SQL Server索引进阶:第一级,索引简介
    2018 – 2019 年前端 JavaScript 面试题
  • 原文地址:https://www.cnblogs.com/ahmasoi/p/6677953.html
Copyright © 2020-2023  润新知