LOJ2125
LOJ2125 树上操作
题目描述
有一棵点数为 N 的树,以点 1 为根,且树有点权。然后有 M 个操作,分为三种:
- 把某个节点 x 的点权增加 aa 。
- 把某个节点 x 为根的子树中所有点的点权都增加 a 。
- 询问某个节点 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的更多相关文章
随机推荐
- IO输入和输出
编程语言的I/O类库中常用使用流这个抽象概念,它代表任何有能力产出数据的数据源对象或者是有能力接收数据的接受端对象."流"屏蔽了实际的I/O设备中处理数据的细节. JAVA类库中的 ...
- java中jna使用回调实现事件监听器——观察者模式
(1)C接口中的接口头文件 #pragma once #include <iostream> #include <vector> #include <core/core. ...
- Rejecting mapping update to [xxx] as the final mapping would have more than 1 type: [xxx, xx]
说明: 1.elasticsearch 版本 6.3.1 2.在同一个index下创建两个type时报错,信息如下: 在创建第二个type:solr时,先前已经在相同索引下创建了一个type:es [ ...
- 关于echarts中的noDataLoadingOption——loading动画的问题
在最近的一个项目中用到echarts这个插件,其中关于noDataLoadingOption配置项的问题让我困惑了好长时间.经过蛋疼的查找下,终于搞明白是版本的原因. 且看官网的介绍:ECharts, ...
- shell实现99乘法表
#!/usr/bin/env sh for ((x=1;x<10;x++));do for ((y=1;x>=y;y++));do printf "${y}x${x}=$(exp ...
- 哎,这让人抠脑壳的 LFU。
这是why哥的第 83 篇原创文章 让人抠脑壳的 LFU 前几天在某APP看到了这样的一个讨论: 看到一个有点意思的评论: LFU 是真的难,脑壳都给我抠疼了. 如果说 LRU 是 Easy 模式的话 ...
- 【Git】5、Git如何提交代码到远程仓库
提交代码:如何把修改后的代码提交到远程仓库 文章目录 提交代码:如何把修改后的代码提交到远程仓库 1.同步远程代码 2.检查改动文件 3.添加文件到缓存 4.提交代码 5.推送代码 6.我的整个流程 ...
- 【Spring】Spring中的Bean - 5、Bean的装配方式(XML、注解(Annotation)、自动装配)
Bean的装配方式 简单记录-Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis)-Spring中的Bean 文章目录 Bean的装配方式 基于XML的装配 基于注解 ...
- 如何跑通第一个 SQL 作业
简介: 本文由阿里巴巴技术专家周凯波(宝牛)分享,主要介绍如何跑通第一个SQL. 一.SQL的基本概念 1.SQL 分类 SQL分为四类,分别是数据查询语言(DQL).数据操纵语言(DML).数据定义 ...
- 【Oracle】add_months()函数介绍
add_months 函数主要是对日期函数进行操作,举例子进行说明 add_months 有两个参数,第一个参数是日期,第二个参数是对日期进行加减的数字(以月为单位的) 如:3个月以后的时间,可以用下 ...