LOJ2125 树上操作

题目描述

有一棵点数为 N 的树,以点 1 为根,且树有点权。然后有 M 个操作,分为三种:

  1. 把某个节点 x 的点权增加 aa 。
  2. 把某个节点 x 为根的子树中所有点的点权都增加 a 。
  3. 询问某个节点 x 到根的路径中所有点的点权和。

输入格式

第一行包含两个整数 N, M。表示点数和操作数。
接下来一行 N 个整数,表示树中节点的初始权值。
接下来 N-1 行每行两个正整数 fr,to , 表示该树中存在一条边(fr,to) 。
再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类(1-3) ,之后接这个操作的参数(x 或者 x a) 。

输出格式

对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

样例

样例输入

5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3

样例输出

6
9
13

数据范围与提示

对于 100% 的数据, N,M≤10^5 ,且所有输入数据的绝对值都不会超过 10^6 。

________________________________________________________________________________________

简单的树链剖分,而且树上的查询也比较简单,只是从某个节点到根的权值和。需要注意的如何处理子树的权值修改。这个就是用到了DFS序。需要记录每个点为跟的子树在线段树中左右边界。

________________________________________________________________________________________

  1 #include<bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const ll maxn=1e5+10;
5 ll n,m;
6 ll w[maxn];
7 struct edge
8 {
9 int u,v,nxt;
10 }e[maxn<<1];
11 ll head[maxn],js;
12 void addage(ll u,ll v)
13 {
14 e[++js].u=u;e[js].v=v;
15 e[js].nxt=head[u];head[u]=js;
16 }
17 ll dep[maxn],siz[maxn],fat[maxn],son[maxn];
18 void dfs(int u,int fa)
19 {
20 siz[u]=1;
21 dep[u]=dep[fa]+1;
22 fat[u]=fa;
23 for(ll i=head[u];i;i=e[i].nxt)
24 {
25 ll v=e[i].v;
26 if(v==fa)continue;
27 dfs(v,u);
28 siz[u]+=siz[v];
29 if(!son[u] || siz[son[u]]<siz[v])son[u]=v;
30 }
31 }
32 ll lp[maxn],rp[maxn],top[maxn],fos[maxn],p;
33 void getpos(ll u,ll fa)
34 {
35 lp[u]=++p;
36 fos[p]=u;
37 top[u]=fa;
38 if(!son[u])
39 {
40 rp[u]=p;
41 return;
42 }
43 getpos(son[u],fa);
44 for(ll i=head[u];i;i=e[i].nxt)
45 {
46 ll v=e[i].v;
47 if(v!=fat[u] && v!=son[u])getpos(v,v);
48 }
49 rp[u]=p;
50 }
51 ll sum[maxn<<2],delt[maxn<<2];
52 inline void updat(ll cur)
53 {
54 sum[cur]=sum[cur<<1]+sum[cur<<1|1];
55 }
56 void build(ll cur,ll l,ll r)
57 {
58 if(l==r)
59 {
60 sum[cur]=w[fos[l]];
61 return;
62 }
63 ll mid=(l+r)>>1;
64 build(cur<<1,l,mid);
65 build(cur<<1|1,mid+1,r);
66 updat(cur);
67 }
68 void down(ll cur,ll l,ll r)
69 {
70 ll mid=(l+r)>>1;
71 delt[cur<<1]+=delt[cur];
72 delt[cur<<1|1]+=delt[cur];
73 sum[cur<<1]+=delt[cur]*(mid-l+1);
74 sum[cur<<1|1]+=delt[cur]*(r-mid);
75 delt[cur]=0;
76 }
77 void add(ll cur,ll l,ll r,ll p,ll x)
78 {
79 if(l==r)
80 {
81 sum[cur]+=x;
82 return ;
83 }
84 ll mid=(l+r)>>1;
85 if(delt[cur])down(cur,l,r);
86 if(p<=mid)add(cur<<1,l,mid,p,x);
87 else add(cur<<1|1,mid+1,r,p,x);
88 updat(cur);
89 }
90 void add_(ll cur,ll l,ll r,ll ql,ll qr,ll x)
91 {
92 if(ql<=l && r<=qr)
93 {
94 sum[cur]+=(r-l+1)*x;
95 delt[cur]+=x;
96 return ;
97 }
98 down(cur,l,r);
99 ll mid=(l+r)>>1;
100 if(ql<=mid)add_(cur<<1,l,mid,ql,qr,x);
101 if(mid<qr)add_(cur<<1|1,mid+1,r,ql,qr,x);
102 updat(cur);
103 }
104 ll query(ll cur,ll l,ll r,ll ql,ll qr)
105 {
106 if(ql<=l && r<=qr)return sum[cur];
107 ll ans=0,mid=(l+r)>>1;
108 if(delt[cur])down(cur,l,r);
109 if(ql<=mid)ans+=query(cur<<1,l,mid,ql,qr);
110 if(mid<qr)ans+=query(cur<<1|1,mid+1,r,ql,qr);
111 return ans;
112 }
113 ll ask(ll x)
114 {
115 ll ans=0;
116 while(x)
117 {
118 ll tpx=top[x];
119 ans+=query(1,1,n,lp[tpx],lp[x]);
120 x=fat[tpx];tpx=top[x];
121 }
122 return ans;
123 }
124 int main()
125 {
126 scanf("%lld%lld",&n,&m);
127 for(int i=1;i<=n;++i)scanf("%lld",w+i);
128 for(ll u,v,i=1;i<n;++i)
129 {
130 scanf("%lld%lld",&u,&v);
131 addage(u,v);addage(v,u);
132 }
133 dfs(1,0);
134 getpos(1,1);
135 build(1,1,n);
136 while(m--)
137 {
138 ll x,a,op;
139 scanf("%lld%lld",&op,&x);
140 if(op!=3)scanf("%lld",&a);
141 if(op==1)add(1,1,n,lp[x],a);
142 else if(op==2)add_(1,1,n,lp[x],rp[x],a);
143 else printf("%lld\n",ask(x));
144 }
145 return 0;
146 }

LOJ2125的更多相关文章

随机推荐

  1. Oracle 使用MERGE INTO 语句 一条语句搞定新增编辑

    MERGE INTO RDP_CHARTS_SETTING T1 USING (SELECT '10001' AS PAGE_ID, 'test' AS CHART_OPTION FROM DUAL) ...

  2. ESP8288-01S/ESP8288-01使用经验总结

    如图:ESP8288-01S/ESP8288-01的区别 超链接 ESP8288-01S/ESP8288-01是乐鑫公司推出的Wi-Fi模块,因为价格便宜迅速占领了市场,它可以做AT指令开发,也可以做 ...

  3. JDK,JRE,JVM三者之间的关系和作用

    1,定义: JDK: Java Develpment Kit java 开发工具 bin:最主要的是编译器(javac.exe) include:java和JVM交互用的头文件 lib:类库 JRE: ...

  4. 从 Eclipse 到 IDEA,金字塔到太空堡垒【转]

    https://blog.csdn.net/X5fnncxzq4/article/details/83829223 工欲善其事,必先利其器.对于程序员来说,具有生产力的工具能让你事半功倍,心情大好.两 ...

  5. devops持续集成

    目录 Devops 版本控制系统 Git安装 Git使用 git四种状态 git基础命令 git分支 git合并冲突 git标签 git命令总结 Github使用 创建仓库 HTTP协议 SSH协议 ...

  6. SonarQube学习(四)- 使用Jenkins集成JaCoCo和SonarQube检查代码测试覆盖率

    一.前言 我始终觉得学习这件事是自己的事,自己会了就是会了,无关于他人,但有点小伤感的是现在的阅读量开始走低. 二.准备 安装Jenkins,请移步<Docker学习(二)- Docker 安装 ...

  7. 递归的三部解题曲 关联leetcode 104. 二叉树最大深度练习

    递归关心的三点 1. 递归的终止条件 2. 一级递归需要做什么 3. 返回给上一级递归的返回值是什么 递归三部曲 1. 找到递归的终止条件:递归什么时候结束 2. 本级递归做什么:在这级递归中应当完成 ...

  8. Flink SQL 核心概念剖析与编程案例实战

    本次,我们从 0 开始逐步剖析 Flink SQL 的来龙去脉以及核心概念,并附带完整的示例程序,希望对大家有帮助! 本文大纲 一.快速体验 Flink SQL 为了快速搭建环境体验 Flink SQ ...

  9. 音视频入门-19-使用giflib处理GIF图片

    * 音视频入门文章目录 * GIFLIB The GIFLIB project 上一篇 [手动生成一张GIF图片], 自己生成了一张 GIF 动态图 rainbow.gif. 下面,使用 GIFLIB ...

  10. 使用SharePoint App-Only获得访问权限

    目前在开发SharePoint Online的过程中,主要使用通过Azure AD的方式获得应用的访问权限,但是SharePoint App-Only的方式依旧被保留了.使用这种方式进行CSOM开发比 ...