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 }