题目链接:https://www.luogu.org/problem/P4315
思路:
我们发现,一个点最多只有一个父亲结点,那么我们就可以考虑把这个点与其父亲结点之间边的边权转化为这个点的点权!那,之后,就变成了我们一开始说的树链剖分裸题了呀!还有一个非常重要的细节就是树链剖分查询和修改路径的时候,父亲结点是不在路径上的!因为父亲结点的点权代表的是它与它的父亲之间的边权,因此,在查询和修改的时候,最后左端点为dfn[x] + 1
1 // luogu-judger-enable-o2 2 #include <stdio.h> 3 #include <algorithm> 4 #include <iostream> 5 #include <stdbool.h> 6 #include <stdlib.h> 7 #include <string> 8 #include <string.h> 9 #include <stack> 10 #include <queue> 11 #include <set> 12 #include <map> 13 #include <math.h> 14 15 #define INF 0x3f3f3f3f 16 #define LL long long 17 using namespace std; 18 19 const int maxn = 300100; 20 21 struct Edge{ 22 int to,next,w; 23 }edge[maxn*4]; 24 25 int head[maxn],tot; 26 int arr[maxn]; 27 28 void add_edge(int u,int v,int w){ 29 edge[++tot] = Edge{v,head[u],w}; 30 head[u] = tot; 31 } 32 33 int p[maxn]; 34 int fa[maxn]; 35 int siz[maxn]; 36 int dep[maxn]; 37 int son[maxn]; 38 39 void dfs1(int u,int f){ 40 siz[u] = 1; 41 fa[u] = f; 42 dep[u] = dep[f] + 1; 43 for (int i=head[u];~i;i=edge[i].next){ 44 int v = edge[i].to; 45 if (v == f) 46 continue; 47 p[v] = edge[i].w; 48 dfs1(v, u); 49 siz[u] += siz[v]; 50 if (siz[son[u]] < siz[v]) 51 son[u] = v; 52 } 53 } 54 55 56 int tim; 57 int dfn[maxn]; 58 int top[maxn]; 59 60 void dfs2(int u,int t){ 61 dfn[u] = ++tim; 62 top[u] = t; 63 arr[tim] = p[u]; 64 if (!son[u]){ 65 return ; 66 } 67 dfs2(son[u],t); 68 for (int i=head[u];~i;i=edge[i].next){ 69 int v = edge[i].to; 70 if (v == fa[u] || v == son[u]){ 71 continue; 72 } 73 dfs2(v,v); 74 } 75 } 76 77 78 struct segment_tree{ 79 int l,r; 80 LL maxval; 81 int lazy; 82 int tag; 83 }tree[maxn*4]; 84 85 void pushup(int nod){ 86 tree[nod].maxval = max(tree[nod<<1].maxval,tree[(nod<<1)+1].maxval); 87 } 88 89 void pushdown(int nod){ 90 if (tree[nod].tag >= 0){ 91 tree[nod<<1].lazy = tree[(nod<<1)+1].lazy = 0; 92 tree[nod<<1].maxval = tree[(nod<<1)+1].maxval = tree[nod<<1].tag = tree[(nod<<1)+1].tag = tree[nod].tag; 93 tree[nod].tag = -1; 94 } 95 if (tree[nod].lazy){ 96 tree[nod<<1].lazy += tree[nod].lazy; 97 tree[(nod<<1)+1].lazy += tree[nod].lazy; 98 tree[nod<<1].maxval += tree[nod].lazy; 99 tree[(nod<<1)+1].maxval += tree[nod].lazy; 100 tree[nod].lazy = 0; 101 } 102 } 103 104 void build (int l,int r,int nod){ 105 tree[nod].tag = -1; 106 tree[nod].l = l; 107 tree[nod].r = r; 108 if ( l == r){ 109 tree[nod].maxval = arr[l]; 110 return ; 111 } 112 int mid = (l + r) >> 1; 113 build(l,mid,nod<<1); 114 build(mid+1,r,(nod<<1)+1); 115 pushup(nod); 116 } 117 118 119 void modify1(int x,int y,int z,int k=1){ 120 int l = tree[k].l, r = tree[k].r; 121 if (x <= l && y >= r){ 122 tree[k].maxval += z; 123 tree[k].lazy += z; 124 return ; 125 } 126 pushdown(k); 127 int mid = (l + r) >> 1; 128 if (x <= mid){ 129 modify1(x,y,z,k<<1); 130 } 131 if (y > mid){ 132 modify1(x,y,z,(k<<1)+1); 133 } 134 pushup(k); 135 } 136 137 138 void modify2(int x,int y,int z,int k=1){ 139 int l = tree[k].l,r = tree[k].r; 140 if (x <= l && y >= r){ 141 tree[k].maxval = tree[k].tag = z; 142 tree[k].lazy = 0; 143 return ; 144 } 145 pushdown(k); 146 int mid = (l + r) >> 1; 147 if (x <= mid) { 148 modify2(x,y,z,k<<1); 149 } 150 if (y > mid){ 151 modify2(x,y,z,(k<<1)+1); 152 } 153 pushup(k); 154 } 155 156 LL cmax(int x,int y,int k=1){ 157 int l = tree[k].l,r = tree[k].r; 158 if (x <= l && y >= r){ 159 return tree[k].maxval; 160 } 161 pushdown(k); 162 int mid = (l + r) >> 1; 163 LL ret = 0; 164 if (x <= mid){ 165 ret = max(ret,cmax(x,y,k<<1)); 166 } 167 if (y > mid){ 168 ret = max(ret,cmax(x,y,(k<<1)+1)); 169 } 170 return ret; 171 } 172 173 174 void mchain1(int x,int y,int z){ 175 while (top[x] != top[y]){ 176 if (dep[top[x]] < dep[top[y]]) 177 swap(x,y); 178 modify1(dfn[top[x]],dfn[x],z); 179 x = fa[top[x]]; 180 } 181 if (dep[x] > dep[y]) 182 swap(x,y); 183 modify1(dfn[x]+1,dfn[y],z); 184 } 185 186 187 void mchain2(int x,int y,int z){ 188 while (top[x] != top[y]){ 189 if (dep[top[x]] < dep[top[y]]) 190 swap(x,y); 191 modify2(dfn[top[x]],dfn[x],z); 192 x = fa[top[x]]; 193 } 194 if (dep[x] > dep[y]) 195 swap(x,y); 196 modify2(dfn[x]+1,dfn[y],z); 197 } 198 199 200 201 LL query_max(int x,int y){ 202 LL ret = 0; 203 while (top[x] != top[y]){ 204 if (dep[top[x]] < dep[top[y]]) 205 swap(x,y); 206 ret = max(ret,cmax(dfn[top[x]],dfn[x],1)); 207 x = fa[top[x]]; 208 } 209 if (dep[x] > dep[y]) 210 swap(x,y); 211 ret = max(ret,cmax(dfn[x]+1,dfn[y],1)); 212 return ret; 213 } 214 215 int main(){ 216 int n; 217 scanf("%d",&n); 218 memset(head,-1, sizeof(head)); 219 for (int i=1;i<=n-1;i++){ 220 int x,y,z; 221 scanf("%d%d%d",&x,&y,&z); 222 add_edge(x,y,z); 223 add_edge(y,x,z); 224 } 225 dfs1(1,0); 226 dfs2(1,1); 227 build(1,n,1); 228 char s[10]; 229 int x,y,z; 230 while (~scanf("%s",s)) { 231 if (strcmp(s, "Stop") == 0) 232 break; 233 if (strcmp(s, "Cover") == 0) { 234 scanf("%d%d%d", &x , &y, &z); 235 mchain2(x,y,z); 236 } else if (strcmp(s, "Add") == 0) { 237 scanf("%d%d%d", &x , &y, &z); 238 mchain1(x,y,z); 239 } else if (strcmp(s, "Change") == 0) { 240 scanf("%d%d", &x, &z); 241 if (dep[edge[2*x-1].to] < dep[edge[2*x].to] ){ 242 x = edge[2*x].to; 243 } 244 else 245 x = edge[2*x-1].to; 246 modify2(dfn[x],dfn[x],z); 247 } 248 else if (strcmp(s, "Max") == 0){ 249 scanf("%d%d",&x,&y); 250 printf("%lld ",query_max(x,y)); 251 } 252 } 253 return 0; 254 }