zoukankan      html  css  js  c++  java
  • Aragorn's Story

    【原题链接】

    【题意说明】

      给一定棵树,并给定各个点权的值,然后有3种操作:
      (1) I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
      (2) D C1 C2 K:把C1与C2的路径上的所有点权值减去K
      (3) Q C:查询节点编号为C的权值

    【问题分析】
      
    典型的树链剖分题目,先进行剖分,然后用线段树去维护即可。

    【参考代码】

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define lson k<<1
    #define rson k<<1|1
    #define lt(i) tree[i].left
    #define rt(i) tree[i].right
    #define nm(i) tree[i].num
    #define tp(i) node[i].top
    #define dp(i) node[i].deep
    #define fa(i) node[i].father
    #define sz(i) node[i].size
    #define sn(i) node[i].son
    #define id(i) node[i].index
    #define hd(i) node[i].head
    #define to(i) edge[i].to
    #define nx(i) edge[i].next
    #define vl(i) node[i].value
    const int maxN=50010;
    struct Tree{
             int left, right, num;
    }tree[maxN<<2];
    struct Node{
             int top, father, deep, size, index, head, son, value;
    }node[maxN];
    struct Edge{
             int to, next;
    }edge[maxN<<1];
    int n, m, q, total;

    bool init();
    void work();
    void addedge(int, int, int);
    void dfs1(int, int);
    void dfs2(int, int);
    void build(int, int, int);
    void update(int, int, int, int);
    int query(int, int);
    void solve(int, int, int);
    void pushdown(int);

    int main(){
             while(init()) work();
             return 0;
    }

    bool init(){
             if(scanf("%d%d%d", &n, &m, &q)==EOF) return false;
             memset(tree, 0, sizeof(tree));
             memset(edge, 0, sizeof(edge));
             memset(node, 0, sizeof(node));
             total=0;
             for(int i=1; i<=n; i++) scanf("%d", &vl(i));
             for(int i=1; i<=m; i++){
                       int x, y;
                       scanf("%d%d", &x, &y);
                       addedge(x, y, i);
                       addedge(y, x, i+n);
             }
             dfs1(1, 1);
             dfs2(1, 1);
             return true;
    }
    void addedge(int x, int y, int k){
             to(k)=y; nx(k)=hd(x); hd(x)=k;
    }

    void dfs1(int k, int _dp){
             sz(k)=1; dp(k)=_dp;
             for(int i=hd(k); i; i=nx(i)){
                       if(sz(to(i))) continue;
                       fa(to(i))=k;
                       dfs1(to(i), _dp+1);
                       sz(k)+=sz(to(i));
                       if(sz(sn(k))<sz(to(i))) sn(k)=to(i);
             }
    }

    void dfs2(int k, int _tp){
             id(k)=++total; tp(k)=_tp;
             if(sn(k)) dfs2(sn(k), _tp);
             for(int i=hd(k); i; i=nx(i))
                       if(!id(to(i))) dfs2(to(i), to(i));
    }

    void work(){
             build(1, 1, n);
             for(int i=1; i<=n; i++)
                       update(1, id(i), id(i), vl(i));
             for(int i=0; i<q; i++){
                       char ch[10];
                       int u, v, w;
                       scanf("%s%d", ch, &u);
                       if(ch[0]=='Q')
                                printf("%d ", query(1, id(u)));
                       else {
                                scanf("%d%d", &v, &w);
                                if(ch[0]=='D')    w=-w;
                                solve(u, v, w);
                       } 
             }
    }

    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 solve(int u, int v, int w){
             int f1=tp(u), f2=tp(v);
             while(f1!=f2){
                       if(dp(f1)<dp(f2)){
                                swap(f1, f2);
                                swap(u, v);
                       }
                       update(1, id(f1), id(u), w);
                       u=fa(f1); f1=tp(u);
             }
             if(dp(u)<dp(v)) swap(u, v);
             update(1, id(v), id(u), w);
    }

    void update(int k, int l, int r, int v){
             if(l<=lt(k)&&r>=rt(k)){
                       nm(k)+=v; return;
             }
             pushdown(k);
             if(l<=rt(lson)) update(lson, l, r, v);
             if(r>=lt(rson)) update(rson, l, r, v);
    }

    void pushdown(int k){
             if(nm(k)){
                       nm(lson)+=nm(k);
                       nm(rson)+=nm(k);
                       nm(k)=0;
             }
    }

    int query(int k, int x){
             if(lt(k)==rt(k)) return nm(k);
             pushdown(k);
             if(x<=rt(lson)) return query(lson, x);
             return query(rson, x);
    }

  • 相关阅读:
    Codeforces Round #733
    [ZJOI2007] 时态同步(树形dp)
    最大子树和(树形dp)
    P2015 二叉苹果树
    没有上司的舞会(经典树形dp)
    P3884 [JLOI2009]二叉树问题(LCA)
    Bin Packing Problem(线段树 + multiset)
    P4281 [AHOI2008]紧急集合 / 聚会(最近公共祖先)
    P3128 [USACO15DEC]Max Flow P(LCA 树上差分)
    java中Set接口用法
  • 原文地址:https://www.cnblogs.com/ahmasoi/p/6678395.html
Copyright © 2011-2022 走看看