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\n", query(x) );
201         }
202     }
203     return 0;
204 }
205 

 

 

posted @ 2019-05-11 15:22  Dybala21  阅读(123)  评论(0编辑  收藏  举报