zoukankan      html  css  js  c++  java
  • [HAOI2015]树上操作

    嘟嘟嘟

    树剖自然可解,就是一道板子题,而且这道题还只问到根节点的距离是多少,而不是树上任意两点距离,就更方便了。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<vector>
      9 #include<stack>
     10 #include<queue>
     11 using namespace std;
     12 #define enter printf("
    ")
     13 #define space printf(" ")
     14 #define Mem(a) memset(a, 0, sizeof(a))
     15 typedef long long ll;
     16 #define int long long
     17 typedef double db;
     18 const int INF = 0x3f3f3f3f;
     19 const int eps = 1e-8;
     20 const int maxn = 1e5 + 5;
     21 inline ll read()
     22 {
     23     ll ans = 0;
     24     char ch = getchar(), last = ' ';
     25     while(!isdigit(ch)) {last = ch; ch = getchar();}
     26     while(isdigit(ch))
     27     {
     28         ans = ans * 10 + ch - '0'; ch = getchar();
     29     }
     30     if(last == '-') ans = -ans;
     31     return ans;
     32 }
     33 inline void write(ll x)
     34 {
     35     if(x < 0) x = -x, putchar('-');
     36     if(x >= 10) write(x / 10);
     37     putchar(x % 10 + '0');
     38 }
     39 
     40 int n, m;
     41 ll a[maxn];
     42 vector<int> v[maxn];
     43 
     44 bool vis[maxn];
     45 int dep[maxn], fa[maxn], son[maxn], size[maxn];
     46 void dfs1(int now)
     47 {
     48     size[now] = 1; vis[now] = 1;
     49     for(int i = 0; i < (int)v[now].size(); ++i)
     50     {
     51         if(!vis[v[now][i]])
     52         {
     53             dep[v[now][i]] = dep[now] + 1;
     54             fa[v[now][i]] = now;
     55             dfs1(v[now][i]);
     56             size[now] += size[v[now][i]];
     57             if(!son[now] || size[v[now][i]] > size[son[now]]) son[now] = v[now][i];
     58         }
     59     }
     60 }
     61 
     62 int dfsx[maxn], pos[maxn], top[maxn], cnt = 0;
     63 void dfs2(int now)
     64 {
     65     vis[now] = 1; dfsx[now] = ++cnt; pos[cnt] = now;
     66     if(son[now])
     67     {
     68         top[son[now]] = top[now];
     69         dfs2(son[now]);
     70     }
     71     for(int i = 0; i < (int)v[now].size(); ++i)
     72     {
     73         if(!vis[v[now][i]] && v[now][i] != son[now])
     74         {
     75             top[v[now][i]] = v[now][i];
     76             dfs2(v[now][i]);
     77         }
     78     }
     79 }
     80 
     81 int l[maxn << 2], r[maxn << 2];
     82 ll sum[maxn << 2], lazy[maxn << 2];
     83 void build(int L, int R, int now)
     84 {
     85     l[now] = L; r[now] = R;
     86     if(L == R) {sum[now] = a[pos[L]]; return;}
     87     int mid = (L + R) >> 1;
     88     build(L, mid, now << 1);
     89     build(mid + 1, R, now << 1 | 1);
     90     sum[now] = sum[now << 1] + sum[now << 1 | 1];
     91 }
     92 void pushdown(int now)
     93 {
     94     if(lazy[now])
     95     {
     96         lazy[now << 1] += lazy[now];
     97         lazy[now << 1 | 1] += lazy[now];
     98         sum[now << 1] += lazy[now] * (r[now << 1] - l[now << 1] + 1);
     99         sum[now << 1 | 1] += lazy[now] * (r[now << 1 | 1] - l[now << 1 | 1] + 1);
    100         lazy[now] = 0;
    101     }
    102 }
    103 void update(int L, int R, int now, int d)
    104 {
    105     if(l[now] == L && r[now] == R) 
    106     {
    107         sum[now] += d * (R - L + 1); 
    108         lazy[now] += d; return;
    109     }
    110     pushdown(now);
    111     int mid = (l[now] + r[now]) >> 1;
    112     if(R <= mid) update(L, R, now << 1, d);
    113     else if(L > mid) update(L, R, now << 1 | 1, d);
    114     else update(L, mid, now << 1, d), update(mid + 1, R, now << 1 | 1, d);
    115     sum[now] = sum[now << 1] + sum[now << 1 | 1];
    116 }
    117 ll query(int L, int R, int now)
    118 {
    119     if(l[now] == L && r[now] == R) return sum[now];
    120     pushdown(now);
    121     int mid = (l[now] + r[now]) >> 1;
    122     if(R <= mid) return query(L, R, now << 1);
    123     else if(L > mid) return query(L, R, now << 1 | 1);
    124     else return query(L, mid, now << 1) + query(mid + 1, R, now << 1 | 1);
    125 }
    126 
    127 ll query_path(int x)
    128 {
    129     ll ret = 0;
    130     while(top[x] != top[1])
    131     {
    132         ret += query(dfsx[top[x]], dfsx[x], 1);
    133         x = fa[top[x]];
    134     }
    135     ret += query(dfsx[top[1]], dfsx[x], 1);
    136     return ret;
    137 }
    138 
    139 main()
    140 {
    141     n = read(); m = read();
    142     for(int i = 1; i <= n; ++i) a[i] = read();
    143     for(int i = 1; i < n; ++i)
    144     {
    145         int x = read(), y = read();
    146         v[x].push_back(y); v[y].push_back(x);
    147     }
    148     dfs1(1); Mem(vis);
    149     top[1] = 1; dfs2(1);        //别忘top[1] = 1 
    150     build(1, cnt, 1);
    151     for(int i = 1; i <= m; ++i)
    152     {
    153         int d = read(), x = read();
    154         if(d == 1) 
    155         {
    156             int c = read();
    157             update(dfsx[x], dfsx[x], 1, c);
    158         }
    159         else if(d == 2)
    160         {
    161             int c = read();
    162             update(dfsx[x], dfsx[x] + size[x] - 1, 1, c);
    163         }
    164         else write(query_path(x)), enter;
    165     }
    166 //    return 0;
    167 }
    View Code

    写完树剖后发现线段树也可以,只要先跑一边dfs序,同时维护每一个点到根节点的路径的权值和,然后修改就是正常的区间修改,因为dfs序满足同一棵子树序号连续。然后单点查询。有兴趣的可以自己写一下~~

  • 相关阅读:
    常用git命令
    复制文件
    实现斗地主洗牌、发牌、看牌
    线程池实现多线程
    git无法提交问题
    Js中处理日期加减天数
    form详解
    node.js中exports与module.exports的区别
    css的direction属性
    webstorm基础使用
  • 原文地址:https://www.cnblogs.com/mrclr/p/9540418.html
Copyright © 2011-2022 走看看