zoukankan      html  css  js  c++  java
  • BZOJ_4034 [HAOI2015]树上操作 【树链剖分dfs序+线段树】

    一 题目

      [HAOI2015]树上操作

    二 分析

      树链剖分的题,这里主要用到了$dfs$序,这题比较简单的就是不用求$lca$。

      1.和树链剖分一样,先用邻接链表建双向图。

      2.跑两遍$dfs$,其实这题可以不这么写,主要是为了确定树型结构转线型后各节点的编号,以及各个链的$top$,$top$很关键,没有$top$就需要不断找父节点。

      3.建线段树,这里一定一定一定要仔细,写太丑就会调很久。o(╯□╰)o

      4.修改操作和常规线段树没有区别,但修改就需要对链上的$top$节点和父节点不断更新,知道找到根节点就可以了。

    三 AC代码

      1 /**************************************************************
      2     Problem: 4034
      3     User: Dybala21
      4     Language: C++
      5     Result: Accepted
      6     Time:2752 ms
      7     Memory:16844 kb
      8 ****************************************************************/
      9  
     10 #include <bits/stdc++.h>
     11 using namespace std;
     12 #define ll long long
     13  
     14 const int MAXN = 1e5 + 14;
     15 int n, m;
     16 int cost[MAXN];
     17 int e[MAXN][2];
     18 struct Edge
     19 {
     20     int to, next;
     21 }edge[MAXN*2];
     22 int head[MAXN], tot;
     23 int fa[MAXN];
     24 int p[MAXN];
     25 int deep[MAXN];
     26 int size[MAXN];
     27 int son[MAXN];
     28 int top[MAXN];
     29 int pos;
     30 void init()
     31 {
     32     tot = 0, pos = 0;
     33     memset(head, -1, sizeof(head));
     34     memset(son, -1, sizeof(son));
     35 }
     36 void addedge(int u, int v)
     37 {
     38     edge[tot].to = v;
     39     edge[tot].next = head[u];
     40     head[u] = tot++;
     41 }
     42 void dfs(int u, int pre, int d)
     43 {
     44     fa[u] = pre;
     45     deep[u] = d;
     46     size[u] = 1;
     47     for(int i = head[u]; i != -1; i = edge[i].next)
     48     {
     49         int v = edge[i].to;
     50         if(v != pre)
     51         {
     52             dfs(v, u, d+1);
     53             size[u] += size[v];
     54             if(son[u] == -1 || size[v] > size[son[u]])
     55                 son[u] = v;
     56         }
     57     }
     58 }
     59 void dfs2(int u, int sp)
     60 {
     61     top[u] = sp;
     62  
     63     if(son[u] != -1)
     64     {
     65         p[u] = ++pos;
     66         dfs2(son[u], sp);
     67     }
     68     else
     69     {
     70         p[u] = ++pos;
     71         return;
     72     }
     73  
     74     for(int i = head[u]; i != -1; i = edge[i].next)
     75     {
     76         int v = edge[i].to;
     77         if(v != son[u] && v != fa[u])
     78             dfs2(v, v);
     79     }
     80 }
     81 struct Node
     82 {
     83     int l, r;
     84     ll sum, lazy;;
     85 }segTree[MAXN*3];
     86 void build(int rt, int l, int r)
     87 {
     88     segTree[rt].l = l;
     89     segTree[rt].r = r;
     90     segTree[rt].lazy = 0;
     91     segTree[rt].sum = 0;
     92     if(l == r)
     93         return;
     94     int mid = (l + r) >> 1;
     95     build(rt<<1, l, mid);
     96     build(rt<<1|1, mid + 1, r);
     97 }
     98 void pushdown(int rt)
     99 {
    100     if(segTree[rt].l == segTree[rt].r)
    101         return;
    102     int mid = (segTree[rt].l + segTree[rt].r)>>1;
    103     ll t = segTree[rt].lazy;
    104     segTree[rt].lazy = 0;
    105     segTree[rt<<1].lazy += t;
    106     segTree[rt<<1|1].lazy += t;
    107     segTree[rt<<1].sum += t*(mid-segTree[rt].l+1);
    108     segTree[rt<<1|1].sum += t*(segTree[rt].r-mid);
    109 }
    110 void update(int rt, int l, int r, ll val)
    111 {
    112     if(segTree[rt].lazy != 0)
    113         pushdown(rt);
    114     if(segTree[rt].l == l && segTree[rt].r == r)
    115     {
    116         segTree[rt].sum += (r-l+1)*val;
    117         segTree[rt].lazy += val;
    118         return;
    119     }
    120     int mid = (segTree[rt].l + segTree[rt].r)>>1;
    121     if(r <= mid)
    122         update(rt<<1, l, r, val);
    123     else if(l > mid)
    124         update(rt<<1|1, l, r, val);
    125     else
    126     {
    127         update(rt<<1, l, mid, val);
    128         update(rt<<1|1, mid + 1, r, val);
    129     }
    130     segTree[rt].sum = segTree[rt<<1].sum + segTree[rt<<1|1].sum;
    131 }
    132 ll query(int rt, int l, int r)
    133 {
    134     if(segTree[rt].lazy)
    135         pushdown(rt);
    136     if(segTree[rt].l == l && segTree[rt].r == r)
    137         return segTree[rt].sum;
    138     int mid = (segTree[rt].l + segTree[rt].r)>>1;
    139     if(r <= mid)
    140         return query(rt<<1, l, r);
    141     else if(l > mid)
    142         return query(rt<<1|1, l, r);
    143     else
    144     {
    145         ll res = 0;
    146         res += query(rt<<1, l, mid);
    147         res += query(rt<<1|1, mid+1, r);
    148         return res;
    149     }
    150 }
    151 ll query(int x)
    152 {
    153     ll ans = 0;
    154     while(top[x] != 1)
    155     {
    156         ans += query(1, p[top[x]], p[x]);
    157         x = fa[top[x]];
    158     }
    159     ans += query(1, 1, p[x]);
    160     return ans;
    161 }
    162 int main()
    163 {
    164     //freopen("in.txt", "r", stdin);
    165     //freopen("out.txt", "w", stdout);
    166     init();
    167     scanf("%d%d", &n, &m);
    168     for(int i = 1; i <= n; i++)
    169     {
    170         scanf("%d", &cost[i]);
    171     }
    172     for(int i = 0; i < n-1; i++)
    173     {
    174         scanf("%d%d", &e[i][0], &e[i][1]);
    175         addedge(e[i][0], e[i][1]);
    176         addedge(e[i][1], e[i][0]);
    177     }
    178     dfs(1, 0, 0);
    179     dfs2(1, 1);
    180     build(1, 1, pos);
    181     for(int i = 1; i <= n; i++)
    182         update(1, p[i], p[i], cost[i]);
    183     int op, x, xa;
    184     for(int i = 0; i < m; i++)
    185     {
    186         scanf("%d", &op);
    187         if(op == 1)
    188         {
    189             scanf("%d%d", &x, &xa);
    190             update(1, p[x], p[x], xa);
    191         }
    192         else if(op == 2)
    193         {
    194             scanf("%d%d", &x, &xa);
    195             update(1, p[x], p[x] + size[x] - 1, xa);
    196         }
    197         else
    198         {
    199             scanf("%d", &x);
    200             printf("%lld
    ", query(x) );
    201         }
    202     }
    203     return 0;
    204 }
    205 

     

  • 相关阅读:
    hdu 3085
    hdu 3295 模拟过程。数据很水
    hdu 2181 水搜索
    pku ppt some problem
    2-sat
    The 2014 ACM-ICPC Asia Mudanjiang Regional First Round
    nenu contest3
    The 10th Zhejiang Provincial Collegiate Programming Contest
    最小费用最大流
    多源最短路
  • 原文地址:https://www.cnblogs.com/dybala21/p/10848792.html
Copyright © 2011-2022 走看看