前言:
之前没学,多校中遇到了很多树上路径问题,速度来补补(板子)
前置技能:dfs序,lca,此处没用上树上差分,用线段树来维护dfs序
拿洛谷例题来说明一下树剖解决的问题:
https://www.luogu.com.cn/problem/P3384
最基础解决的问题就是树上路径的问题:求两个u,v,多次修改查询,u到v的路径和
首先我们明确,两点间的最短路径一定是经过lca的一条路径,也就是我们实际上就需要找
lca到u的链和lca到v的链
把一棵树分成多条重链和轻链
概念:
- 重儿子:对于每一个非叶子节点,它的儿子中 儿子数量最多的那一个儿子 为该节点的重儿子
- 轻儿子:对于每一个非叶子节点,它的儿子中 非重儿子 的剩下所有儿子即为轻儿子
- 叶子节点没有重儿子也没有轻儿子(因为它没有儿子。。)
- 重边:连接任意两个重儿子的边叫做重边
- 轻边:剩下的即为轻边
- 重链:相邻重边连起来的 连接一条重儿子 的链叫重链
- 对于叶子节点,若其为轻儿子,则有一条以自己为起点的长度为1的链
- 每一条重链以轻儿子为起点
我们先用两次搜索将重链和轻链划分:
void dfs1(int u,int f) { dep[u]=dep[f]+1;//深度 fa[u]=f;//记录父亲 siz[u]=1;//子结点大小 int maxson=-1; for(int i=head[u];i;i=e[i].next) { int v=e[i].v; if(v!=f) { dfs1(v,u); siz[u]+=siz[v]; if(siz[v]>maxson) son[u]=v,maxson=siz[v];//更新 } } }
void dfs2(int u,int t) { dfn[u]=++idx;//dfs序 top[u]=t;//重链头 w[idx]=dis[u];//dfs序上的点权值 if(!son[u]) return; dfs2(son[u],t); for(int i=head[u];i;i=e[i].next) { int v=e[i].v; if(v!=fa[u]&&v!=son[u]) dfs2(v,v); } }
利用dfs序,一条链上的序号是连续的,也就是一段连续区间可以表示一个链,记录就行了,变成了线段树操作
洛谷板子完整代码:
1 #include <iostream> 2 #include <algorithm> 3 #include <string> 4 #include <vector> 5 #include <stack> 6 #include <cstring> 7 #include <cmath> 8 #include <cstdio> 9 #include <unordered_map> 10 #include <queue> 11 #include <map> 12 #include <sstream> 13 #include <set> 14 #include <cstdlib> 15 #include <ctime> 16 #include <unordered_set> 17 #include <bitset> 18 #include <chrono> 19 using namespace std; 20 typedef unsigned long long ull; 21 typedef long long ll; 22 //#pragma GCC optimize(3, "Ofast", "inline") 23 #define MAX_INF 0x3f3f3f3f 24 template <class T, class C> 25 void print(C name, T a) 26 { 27 cout << name << ": " << a << endl; 28 } 29 template <class T> 30 T gcd(T a, T b) 31 { 32 return b ? gcd(b, a % b) : a; 33 } 34 template <class T> 35 T lcm(T a, T b) 36 { 37 return a * b / gcd(a, b); 38 } 39 ll pow(ll a, ll b, ll p) 40 { 41 ll ans = 1; 42 a %= p; 43 while (b) 44 { 45 if (b & 1) 46 ans = ans * a % p; 47 a = a * a % p; 48 b >>= 1; 49 } 50 return ans; 51 } 52 template <typename _Tp> 53 void read(_Tp &x) 54 { 55 char ch; 56 bool flag = 0; 57 x = 0; 58 while (ch = getchar(), !isdigit(ch)) 59 if (ch == '-') 60 flag = 1; 61 while (isdigit(ch)) 62 x = x * 10 + ch - '0', ch = getchar(); 63 if (flag) 64 x = -x; 65 } 66 template <class T> 67 void print(T x) 68 { 69 if (x < 0) 70 { 71 x = -x; 72 putchar('-'); 73 } 74 if (x > 9) 75 print(x / 10); 76 putchar(x % 10 + '0'); 77 } 78 ll mod = 998244353; 79 const ll inf = 1e18; 80 #define fir(i, a, b) for (int i = a; i <= b; i++) 81 const int maxn = 1e5 + 20, N = 1e5+20, M = 3000 + 10; 82 struct node 83 { 84 int v; 85 int next; 86 }; 87 int dep[maxn],fa[maxn],son[maxn],siz[maxn],head[maxn]; 88 ll dis[maxn],w[maxn]; 89 int dfn[maxn],idx=0,top[maxn]; 90 node e[maxn<<1]; 91 int tot=0; 92 void add(int x,int y) 93 { 94 e[++tot] = {y, head[x]}, head[x] = tot; 95 } 96 ll add(ll x, ll t,ll mod) { 97 x %= mod;t %= mod;return (x + t) % mod; 98 } 99 void dfs1(int u,int f) 100 { 101 dep[u]=dep[f]+1; 102 fa[u]=f; 103 siz[u]=1; 104 int maxson=-1; 105 for(int i=head[u];i;i=e[i].next) 106 { 107 int v=e[i].v; 108 if(v!=f) 109 { 110 dfs1(v,u); 111 siz[u]+=siz[v]; 112 if(siz[v]>maxson) 113 son[u]=v,maxson=siz[v]; 114 } 115 } 116 } 117 void dfs2(int u,int t) 118 { 119 dfn[u]=++idx; 120 top[u]=t; 121 w[idx]=dis[u]; 122 if(!son[u]) 123 return; 124 dfs2(son[u],t); 125 for(int i=head[u];i;i=e[i].next) 126 { 127 int v=e[i].v; 128 if(v!=fa[u]&&v!=son[u]) 129 dfs2(v,v); 130 } 131 } 132 #define left (i<<1) 133 #define right (i<<1|1) 134 struct Segnode 135 { 136 int l; 137 int r; 138 ll sum; 139 ll add; 140 }; 141 Segnode sgt[maxn<<2]; 142 inline void push_up(int i) 143 { 144 sgt[i].sum=(sgt[left].sum+sgt[right].sum)%mod; 145 } 146 void build(int l,int r,int i) 147 { 148 sgt[i].l=l; 149 sgt[i].r=r; 150 if(l==r) 151 { 152 sgt[i].sum=w[l]; 153 return; 154 } 155 int mid=(l+r)>>1; 156 build(l,mid,left); 157 build(mid+1,r,right); 158 push_up(i); 159 } 160 inline void push_down(int i) 161 { 162 if(sgt[i].add) 163 { 164 sgt[left].sum=add(sgt[left].sum,sgt[i].add*(sgt[left].r-sgt[left].l+1),mod); 165 sgt[left].add+=sgt[i].add; 166 sgt[right].sum=add(sgt[right].sum,sgt[i].add*(sgt[right].r-sgt[right].l+1),mod); 167 sgt[right].add+=sgt[i].add; 168 sgt[i].add=0; 169 } 170 } 171 ll query(int l,int r,int i) 172 { 173 if(l<=sgt[i].l&&sgt[i].r<=r) 174 { 175 return sgt[i].sum; 176 } 177 push_down(i); 178 int mid=(sgt[i].l+sgt[i].r)>>1; 179 ll ans=0; 180 if(l<=mid) 181 ans=add(ans,query(l,r,left),mod); 182 if(r>mid) 183 ans=add(ans,query(l,r,right),mod); 184 push_up(i); 185 return ans; 186 } 187 void change(int l,int r,int i,ll x) 188 { 189 if(l<=sgt[i].l&&sgt[i].r<=r) 190 { 191 sgt[i].sum=add(sgt[i].sum,(sgt[i].r-sgt[i].l+1)*x,mod); 192 sgt[i].add=add(sgt[i].add,x,mod); 193 return; 194 } 195 push_down(i); 196 int mid=(sgt[i].l+sgt[i].r)>>1; 197 if(l<=mid) 198 change(l,r,left,x); 199 if(r>mid) 200 change(l,r,right,x); 201 push_up(i); 202 } 203 void mofidy(int x,int y,ll z) 204 { 205 while(top[x]!=top[y]) 206 { 207 if(dep[top[x]]<dep[top[y]])swap(x,y); 208 change(dfn[top[x]],dfn[x],1,z); 209 x=fa[top[x]]; 210 } 211 if(dep[x]>dep[y]) 212 swap(x,y); 213 change(dfn[x],dfn[y],1,z); 214 } 215 ll qrange(int x,int y) 216 { 217 ll ans=0; 218 while(top[x]!=top[y]) 219 { 220 if(dep[top[x]]<dep[top[y]])swap(x,y); 221 ans=add(ans,query(dfn[top[x]],dfn[x],1),mod); 222 x=fa[top[x]]; 223 } 224 if(dep[x]>dep[y]) 225 swap(x,y); 226 ans=add(ans,query(dfn[x],dfn[y],1),mod); 227 return ans; 228 } 229 int main() 230 { 231 int n,Q,root; 232 cin>>n>>Q>>root>>mod; 233 fir(i,1,n) 234 scanf("%lld",&dis[i]); 235 fir(i,1,n-1) 236 { 237 int x,y; 238 scanf("%d%d",&x,&y); 239 add(x,y),add(y,x); 240 } 241 dfs1(root,0); 242 dfs2(root,0); 243 build(1,idx,1); 244 while(Q--) 245 { 246 int ch; 247 scanf("%d",&ch); 248 int x,y;ll z; 249 if(ch==1) 250 { 251 scanf("%d%d%lld",&x,&y,&z); 252 mofidy(x,y,z); 253 } 254 else if(ch==2) 255 { 256 scanf("%d%d",&x,&y); 257 ll ans=qrange(x,y); 258 printf("%lld\n",ans); 259 } 260 else if(ch==3) 261 { 262 scanf("%d%lld",&x,&z); 263 change(dfn[x],dfn[x]+siz[x]-1,1,z); 264 } 265 else 266 { 267 scanf("%d",&x); 268 printf("%lld\n",query(dfn[x],dfn[x]+siz[x]-1,1)); 269 } 270 } 271 }

浙公网安备 33010602011771号