zoukankan      html  css  js  c++  java
  • HDU 3966 (树链剖分+线段树)

    Problem Aragorn's Story (HDU 3966)

    题目大意

      给定一颗树,有点权。

      要求支持两种操作,将一条路径上的所有点权值增加或减少ai,询问某点的权值。

    解题分析

      树链剖分模板题。

      实质上树链剖分进行了点对点的一次映射,保证了重链上的点在线段树上的位置是连续的。

      树链剖分的两个性质(转):

        性质1:如果(v,u)为轻边,则siz[u] * 2 < siz[v];

        性质2:从根到某一点的路径上轻链、重链的个数都不大于logn。

      保证了一个区间的时间复杂度是log2(n)。

      要分清3种标号含义(易混) :树中节点标号,树中节点对应线段树中位置标号,线段树中区间标号。

      树链剖分相关数组意义 :

        size[i] :以i为根的子树的大小

        fa[i] :i节点的父亲

        dep[i] :i节点的深度

        son[i] :i节点的重儿子(所有儿子中size最大的)

        w[i] :i节点在线段树中对应的位置

        top[i] :i节点所在重链的顶端节点,若为轻链,则为自身。

        rank[i] :线段树中所对应树中节点。

    参考程序

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <cmath>
      5 
      6 #define V 50008
      7 #define E 100008
      8 #define lson l,m,rt<<1
      9 #define rson m+1,r,rt<<1|1
     10 
     11 int n,m,Q;
     12 int a[V],size[V],dep[V],fa[V],top[V],w[V],son[V],rank[V];
     13 int sum[V << 2],lazy[V << 2];
     14 
     15 struct line{
     16     int u,v,nt;
     17 }eg[E];
     18 int lt[V],summ,cnt;
     19 
     20 void adt(int u,int v){
     21     eg[++summ].u=u; eg[summ].v=v; eg[summ].nt=lt[u]; lt[u]=summ;
     22 }
     23 
     24 void add(int u,int v){
     25     adt(u,v); adt(v,u);
     26 }
     27 
     28 void dfs1(int u){
     29     size[u]=1; son[u]=0;
     30     for (int i=lt[u];i;i=eg[i].nt){
     31         int v=eg[i].v;
     32         if (v!=fa[u]){
     33             fa[v]=u;
     34             dep[v]=dep[u]+1;
     35             dfs1(v);
     36             size[u]+=size[v];
     37             if (size[v]>size[son[u]]) son[u]=v;
     38         }
     39     }
     40 }
     41 
     42 void dfs2(int u,int tp,int x){
     43     top[u]=tp; w[u]=++cnt; rank[cnt]=u;
     44     if (son[u]) dfs2(son[u],tp,1);
     45     for (int i=lt[u];i;i=eg[i].nt){
     46         int v=eg[i].v;
     47         if (v==son[u] || v==fa[u]) continue;
     48         dfs2(v,v,2);
     49     }
     50 }
     51 
     52 void init(){
     53     memset(lt,0,sizeof(lt));
     54     summ=1; cnt=0;
     55     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
     56     for (int i=1;i<=m;i++){
     57         int u,v;
     58         scanf("%d %d",&u,&v);
     59         add(u,v);
     60     }
     61     dep[1]=1; fa[1]=0; 
     62     dfs1(1);
     63     dfs2(1,1,1);
     64 }
     65 
     66 void pushup(int rt){
     67     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
     68 }
     69 
     70 void pushdown(int rt,int m){
     71     if (lazy[rt]){
     72         lazy[rt<<1]+=lazy[rt];
     73         lazy[rt<<1|1]+=lazy[rt];
     74         sum[rt<<1]+=lazy[rt]*(m-m / 2);
     75         sum[rt<<1|1]+=lazy[rt]*(m / 2);
     76         lazy[rt]=0;
     77     }
     78 }
     79 
     80 void build(int l,int r,int rt){
     81     lazy[rt]=0;
     82     if (l==r){
     83         sum[rt]=a[rank[l]];
     84         return;
     85     }
     86     int m=(l+r)/2;
     87     build(lson);
     88     build(rson);
     89     pushup(rt);
     90 }
     91 
     92 void update(int L,int R,int val,int l,int r,int rt){
     93     if (L<=l && r<=R){
     94         sum[rt]+=val*(r-l+1);
     95         lazy[rt]+=val;
     96         return;
     97     }
     98     pushdown(rt,r-l+1);
     99     int m=(l+r)>>1;
    100     if (L<=m) update(L,R,val,lson);
    101     if (m< R) update(L,R,val,rson);
    102     pushup(rt);
    103 }
    104 
    105 int query(int x,int l,int r,int rt){
    106     if (l==r){
    107         return sum[rt];
    108     }
    109     pushdown(rt,r-l+1);
    110     int m=(l+r)>>1;
    111     if (x<=m) return query(x,lson);
    112     if (m< x) return query(x,rson);
    113 }
    114 
    115 void change(int x,int y,int val){
    116     while (top[x]!=top[y]){
    117         if (dep[top[x]]<dep[top[y]]) std::swap(x,y);
    118         update(w[top[x]],w[x],val,1,n,1);
    119         x=fa[top[x]];
    120     }
    121     if (dep[x]>dep[y]) std::swap(x,y);
    122     update(w[x],w[y],val,1,n,1);
    123 }
    124 
    125 int main(){
    126     while (~scanf("%d %d %d",&n,&m,&Q)){
    127         init();
    128         build(1,n,1);
    129         while (Q--){
    130             char s[2];
    131             int x,y,z;
    132             scanf("%s",s);
    133             if (s[0]=='I'){
    134                 scanf("%d %d %d",&x,&y,&z);
    135                 change(x,y,z);
    136             }    
    137             if (s[0]=='D'){
    138                 scanf("%d %d %d",&x,&y,&z);
    139                 change(x,y,-z);
    140             }
    141             if (s[0]=='Q'){
    142                 scanf("%d",&x);
    143                 printf("%d
    ",query(w[x],1,n,1));
    144             }
    145         }
    146     }
    147 }
    View Code
  • 相关阅读:
    LintCode "Maximum Gap"
    LintCode "Wood Cut"
    LintCode "Expression Evaluation"
    LintCode "Find Peak Element II"
    LintCode "Remove Node in Binary Search Tree"
    LintCode "Delete Digits"
    LintCode "Binary Representation"
    LeetCode "Game of Life"
    LintCode "Coins in a Line"
    LintCode "Word Break"
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/5722270.html
Copyright © 2011-2022 走看看