4034: [HAOI2015]树上操作

4034: [HAOI2015]树上操作

链接

思路:

  树链剖分。操作:单点修改,路径查询,子树修改。

代码:

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<cmath>
  6 #include<cctype>
  7
  8 using namespace std;
  9
 10 const int N = 100100;
 11 typedef long long LL;
 12
 13 struct Edge{
 14     int to,nxt;
 15     Edge() {}
 16     Edge(int a,int b) {to = a,nxt = b;}
 17 }e[N<<1];
 18 int head[N],tot;
 19 LL sum[N<<2],tag[N<<2],w[N],data[N];
 20 int pos[N],siz[N],son[N],bel[N],deth[N],fa[N];
 21 int tn;
 22
 23 inline int read() {
 24     int x = 0,f = 1;char ch = getchar();
 25     for (; !isdigit(ch); ch=getchar()) if(ch==‘-‘) f = -1;
 26     for (; isdigit(ch); ch=getchar()) x = x*10+ch-‘0‘;
 27     return x * f;
 28 }
 29 void add_edge(int u,int v) {
 30     e[++tot] = Edge(v,head[u]);head[u] = tot;
 31     e[++tot] = Edge(u,head[v]);head[v] = tot;
 32 }
 33 void dfs1(int u,int pa) {
 34     siz[u] = 1;
 35     deth[u] = deth[pa] + 1;
 36     fa[u] = pa;
 37     for (int i=head[u]; i; i=e[i].nxt) {
 38         int v = e[i].to;
 39         if (v==pa) continue;
 40         dfs1(v,u);
 41         siz[u] += siz[v];
 42         if (!son[u] || siz[son[u]]<siz[v]) son[u] = v;
 43     }
 44 }
 45 void dfs2(int u,int top) {
 46     bel[u] = top;
 47     pos[u] = ++tn;
 48     data[pos[u]] = w[u];
 49     if (!son[u]) return;
 50     dfs2(son[u],top);
 51     for (int i=head[u]; i; i=e[i].nxt) {
 52         int v = e[i].to;
 53         if (v==fa[u] || v==son[u]) continue;
 54         dfs2(v,v);
 55     }
 56 }
 57
 58 #define lson l,mid,rt<<1
 59 #define rson mid+1,r,rt<<1|1
 60
 61 void pushup(int rt) {
 62     sum[rt] = sum[rt<<1] + sum[rt<<1|1];
 63 }
 64 void pushdown(int rt,int len) {
 65     if (tag[rt]) {
 66         sum[rt<<1] += 1ll * tag[rt] * (len-len/2);tag[rt<<1] += tag[rt];
 67         sum[rt<<1|1] += 1ll * tag[rt] * (len/2);tag[rt<<1|1] += tag[rt];
 68         tag[rt] = 0;
 69     }
 70 }
 71 void build(int l,int r,int rt) {
 72     if (l==r) {
 73         sum[rt] = data[l];
 74         return ;
 75     }
 76     int mid = (l + r) / 2;
 77     build (lson);
 78     build (rson);
 79     pushup(rt);
 80 }
 81 void update(int l,int r,int rt,int L,int R,LL x) {
 82     if (L <= l && r <= R) {
 83         sum[rt] += 1ll * (r - l + 1) * x;
 84         tag[rt] += x;
 85         return ;
 86     }
 87     pushdown(rt,r-l+1);
 88     int mid = (l + r) / 2;
 89     if (L <= mid) update(lson,L,R,x);
 90     if (R > mid)  update(rson,L,R,x);
 91     pushup(rt);
 92 }
 93 LL query(int l,int r,int rt,int L,int R) {
 94     if (L <= l && r <= R) {
 95         return sum[rt];
 96     }
 97     int mid = (l + r) / 2;
 98     LL ret = 0;
 99     pushdown(rt,r-l+1);
100     if (L <= mid) ret += query(lson,L,R);
101     if (R > mid)  ret += query(rson,L,R);
102     return ret;
103 }
104 void Ask(int x,int y) {
105     LL ans = 0;
106     while (bel[x] != bel[y]) {
107         if (deth[bel[x]] < deth[bel[y]]) swap(x,y);
108         ans += query(1,tn,1,pos[bel[x]],pos[x]);
109         x = fa[bel[x]];
110     }
111     if (deth[x] < deth[y]) swap(x,y);
112     ans += query(1,tn,1,pos[y],pos[x]);
113     printf("%lld\n",ans);
114 }
115 int main() {
116     int n = read(),m = read();
117     for (int i=1; i<=n; ++i) w[i] = read();
118     for (int i=1; i<n; ++i) {
119         int u = read(),v = read();
120         add_edge(u,v);
121     }
122     dfs1(1,0);
123     dfs2(1,1);
124     build(1,tn,1);
125     LL a;
126     while (m--) {
127         int opt = read(),x = read();
128         if (opt == 1) {
129             a = read();
130             update(1,tn,1,pos[x],pos[x],a);
131         }
132         else if (opt==2) {
133             a = read();
134             update(1,tn,1,pos[x],pos[x]+siz[x]-1,a);
135         }
136         else Ask(x,1);
137     }
138     return 0;
139 }

原文地址:https://www.cnblogs.com/mjtcn/p/9062811.html

时间: 2024-08-25 10:44:17

4034: [HAOI2015]树上操作的相关文章

bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树

4034: [HAOI2015]树上操作 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4352  Solved: 1387[Submit][Status][Discuss] Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有

BZOJ 4034 HAOI2015 树上操作

4034: [HAOI2015]树上操作 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 6033  Solved: 1959[Submit][Status][Discuss] Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有

洛谷 P3178 BZOJ 4034 [HAOI2015]树上操作

题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a .操作 3 :询问某个节点 x 到根的路径中所有点的点权和. 输入输出格式 输入格式: 第一行包含两个整数 N, M .表示点数和操作数.接下来一行 N 个整数,表示树中节点的初始权值.接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) .再接下来 M 行

BZOJ 4034[HAOI2015]树上操作(树链剖分)

Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a .操作 3 :询问某个节点 x 到根的路径中所有点的点权和.Input 第一行包含两个整数 N, M .表示点数和操作数.接下来一行 N 个整数,表示树中节点的初始权值.接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) .再接下来 M 行,

bzoj千题计划242:bzoj4034: [HAOI2015]树上操作

http://www.lydsy.com/JudgeOnline/problem.php?id=4034 dfs序,树链剖分 #include<cstdio> #include<iostream> using namespace std; #define N 100001 typedef long long LL; int n,a[N]; int front[N],nxt[N<<1],to[N<<1],tot; int fa[N],siz[N],dep[N]

bzoj4034: [HAOI2015]树上操作(树剖)

4034: [HAOI2015]树上操作 题目:传送门 题解: 树剖裸题: 麻烦一点的就只有子树修改(其实一点也不),因为子树编号连续啊,直接改段(记录编号最小和最大) 开个long long 水模版 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std

【BZOJ4034】[HAOI2015]树上操作 树链剖分+线段树

[BZOJ4034][HAOI2015]树上操作 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. Input 第一行包含两个整数 N, M .表示点数和操作数. 接下来一行 N 个整数,表示树中节点的初始权值. 接下来 N-1 行每行三个正整数 fr, to

[HAOI2015]树上操作

[HAOI2015]树上操作 2017-09-07 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. Input 第一行包含两个整数 N, M .表示点数和操作数.接下来一行 N 个整数,表示树中节点的初始权值.接下来 N-1 行每行三个正整数 fr, to ,

[HAOI2015]树上操作 -树链剖分

1963. [HAOI2015]树上操作 [题目描述] 有一棵点数为N的树,以点1为根,且树点有权值.然后有M个操作,分为三种: 操作1:把某个节点x的点权增加a. 操作2:把某个节点x为根的子树中所有点的点权都增加a. 操作3:询问某个节点x到根的路径中所有点的点权和. [输入格式] 第一行两个整数N,M,表示点数和操作数. 接下来一行N个整数,表示树中节点的初始权值. 接下来N-1行每行两个正整数fr,to,表示该树中存在一条边(fr,to). 再接下来M行,每行分别表示一次操作.其中第一个