[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("\n")
 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序满足同一棵子树序号连续。然后单点查询。有兴趣的可以自己写一下~~

 

转载于:https://www.cnblogs.com/mrclr/p/9540418.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值