记录编号 |
318112 |
评测结果 |
AAAAAAAAAA |
题目名称 |
[HAOI 2015]树上操作 |
最终得分 |
100 |
用户昵称 |
小e |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
1.229 s |
提交时间 |
2016-10-08 21:03:20 |
内存使用 |
114.85 MiB |
显示代码纯文本
- #include "stdio.h"
- #include "stdlib.h"
- typedef long long LL;
-
- const int maxnumber = 1001000;
- struct Edge
- {
- int to, next;
- }edges[maxnumber << 1];
- int head[maxnumber], tot;
- int n, m;
- LL value[maxnumber], num;
- int depth[maxnumber], size[maxnumber], fa[maxnumber], son[maxnumber];
- int dfn[maxnumber], id[maxnumber], top[maxnumber], dfsclock;
- LL tree[maxnumber << 2], lazy[maxnumber << 2];
-
- template <class T> inline void Read(T& a)
- {
- a = 0;
- int minus = 1;
- char ch = getchar();
- if(ch == '-') minus = -1;
- while(ch < '0' || ch > '9'){
- ch = getchar();
- if(ch == '-') minus = -1;
- }
- while(ch >= '0' && ch <= '9'){
- a = a * 10 + ch - '0';
- ch = getchar();
- }
- a = a * minus;
- }
-
- template <class T> inline void Write(T a)
- {
- int cnt = 0;
- if(a < 0){
- putchar('-');
- a = -a;
- }
- char ch[50] = {'\0'};
- while(1){
- ch[++cnt] = a % 10 + '0';
- a /= 10;
- if(!a) break;
- }
- while(cnt)
- putchar(ch[cnt--]);
- puts("");
- }
-
- template <class T> inline void Swap(T& a, T& b)
- {
- T tmp = a;
- a = b;
- b = tmp;
- }
-
- inline void AddEdge(const int& from, const int& to)
- {
- edges[++tot].to = to;
- edges[tot].next = head[from];
- head[from] = tot;
- }
-
- void Segment_Tree_Build(const int& l, const int& r, const int& rt)
- {
- // printf("l:%d r:%d rt:%d\n", l, r, rt); while(1);
- if(l == r){
- tree[rt] = value[id[l]];
- return;
- }
- const int mid = (l + r) >> 1, lch = rt << 1, rch = lch | 1;
- Segment_Tree_Build(l, mid, lch);
- Segment_Tree_Build(mid+1, r, rch);
- tree[rt] = tree[lch] + tree[rch];
- }
-
- inline void PushDown(const int l, const int r, const int& rt)
- {
- const int mid = (l + r) >> 1,lch = rt << 1, rch = lch | 1;
- lazy[lch] += lazy[rt]; lazy[rch] += lazy[rt];
- tree[lch] += (LL)(mid - l + 1) * lazy[rt];
- tree[rch] += (LL)(r - mid) * lazy[rt];
- lazy[rt] = 0;
- }
-
- void Segment_Tree_Add(const int& l, const int& r, const int& rt, const int& s, const int& t)
- {
- if(s <= l && t >= r){
- tree[rt] += (r - l + 1) * num;
- lazy[rt] += num;
- return;
- }
- if(lazy[rt]) PushDown(l, r, rt);
- const int mid = (l + r) >> 1, lch = rt << 1, rch = lch | 1;
- if(t <= mid) Segment_Tree_Add(l, mid, lch, s, t);
- else if(s >= mid + 1) Segment_Tree_Add(mid+1, r, rch, s, t);
- else{
- Segment_Tree_Add(l, mid, lch, s, mid);
- Segment_Tree_Add(mid+1, r, rch, mid+1, t);
- }
- tree[rt] = tree[lch] + tree[rch];
- }
-
- LL Segment_Tree_Sum(const int& l, const int& r, const int& rt, const int& s, const int& t)
- {
- if(s <= l && t >= r) return tree[rt];
- if(lazy[rt]) PushDown(l, r, rt);
- const int mid = (l + r) >> 1, lch = rt << 1, rch = lch | 1;
- if(t <= mid) return Segment_Tree_Sum(l, mid, lch, s, t);
- else if(s >= mid + 1) return Segment_Tree_Sum(mid+1, r, rch, s, t);
- return Segment_Tree_Sum(l, mid, lch, s, mid) + Segment_Tree_Sum(mid+1, r, rch, mid+1, t);
- }
-
- void DFS1(const int& a)
- {
- size[a] = 1;
- for(int i = head[a]; i; i = edges[i].next){
- int to = edges[i].to;
- if(to == fa[a]) continue;
- depth[to] = depth[a] + 1;
- fa[to] = a;
- DFS1(to);
- size[a] += size[to];
- if(size[to] > size[son[a]]) son[a] = to;
- }
- }
-
- void DFS2(const int& a, const int& tp)
- {
- dfn[a] = ++dfsclock;
- id[dfsclock] = a;
- top[a] = tp;
- if(son[a]) DFS2(son[a], tp);
- for(int i = head[a]; i; i = edges[i].next){
- int to = edges[i].to;
- if(to == fa[a] || to == son[a]) continue;
- DFS2(to, to);
- }
- }
-
- inline LL Query(int s, int t)
- {
- LL ret = 0;
- int f1 = top[s], f2 = top[t];
- while(f1 != f2){
- if(depth[f1] < depth[f2]){
- Swap(f1, f2);
- Swap(s, t);
- }
- ret += Segment_Tree_Sum(1, n, 1, dfn[f1], dfn[s]);
- s = fa[f1];
- f1 = top[s];
- }
- if(depth[s] < depth[t]) Swap(s, t);
- ret += Segment_Tree_Sum(1, n, 1, dfn[t], dfn[s]);
- return ret;
- }
-
- #define SUBMIT
- int main(int argc, char const *argv[])
- {
- #ifdef SUBMIT
- freopen("haoi2015_t2.in", "r", stdin); freopen("haoi2015_t2.out", "w", stdout);
- #endif
-
- int from, to, order, s;
- Read(n); Read(m);
- for(int i = 1; i <= n; i++) Read(value[i]);
- for(int i = 1; i < n; i++){
- Read(from); Read(to);
- AddEdge(from, to);
- AddEdge(to, from);
- }
-
- depth[1] = 1;
- DFS1(1);
- DFS2(1, 1);
- Segment_Tree_Build(1, n, 1);
-
- for(int i = 1; i <= m; i++){
- Read(order);
- if(order == 1){
- Read(s); Read(num);
- Segment_Tree_Add(1, n, 1, dfn[s], dfn[s]);
- }
- else if(order == 2){
- Read(s); Read(num);
- Segment_Tree_Add(1, n, 1, dfn[s], dfn[s] + size[s] - 1);
- }
- else{
- Read(s);
- Write(Query(s, 1));
- }
- }
-
- #ifndef SUBMIT
- printf("\n----------\n");
- getchar(); getchar();
- #else
- fclose(stdin); fclose(stdout);
- #endif
-
- return 0;
- }