[luogu]月下“毛景树”:树 剖 好 题
Posted chiarochinoful
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luogu]月下“毛景树”:树 剖 好 题相关的知识,希望对你有一定的参考价值。
题意:
给一棵树 , 每一条边都有边权 , 支持四种操作
1. 将第k条边权值修改为k
2. 将节点u到v的边权都覆盖为k
3. 将节点u到v的边权都增加k
4. 询问区间边权最大值
显然树剖
边权转点权然后就是树剖裸题了
怎样边权转点权
对于一个点u , 她的父亲是 v
将 u->v 的边权放到 u 上做点权
然后树剖最后的时候这样操作一波
1 if(a == b) 2 return; 3 if(dep[a] > dep[b]) 4 std::swap(a, b); 5 SgCover(1, id[a] + 1, id[b], k);
这样就保证了这两个点的 LCA 的点权不会被统计(LCA的点权指向的是 LCA->fa[LCA] , 很显然不能统计)
另一个问题 , 线段树的lazytag
我维护了两个懒标记
一个是 cov , 是覆盖的懒标记
一个是 add , 是增加的懒标记
至于具体用法还是看代码吧 ... 挺好理解的
代码:
1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<iostream> 6 #include<algorithm> 7 #define APART puts("----------------------") 8 #define debug 1 9 #define FILETEST 1 10 #define inf 100010 11 #define ll long long 12 #define ha 998244353 13 #define INF 0x7fffffff 14 #define INF_T 9223372036854775807 15 #define DEBUG printf("%s %d\n",__FUNCTION__,__LINE__) 16 17 namespace chino 18 19 inline void setting() 20 #if FILETEST 21 freopen("_test.in", "r", stdin); 22 freopen("_test.me.out", "w", stdout); 23 #endif 24 return; 25 26 27 inline int read() 28 char c = getchar(), up = c; int num = 0; 29 for(; c < ‘0‘ || c > ‘9‘; up = c, c = getchar()); 30 for(; c >= ‘0‘ && c <= ‘9‘; num = (num << 3) + (num << 1) + (c ^ ‘0‘), c = getchar()); 31 return up == ‘-‘ ? -num : num; 32 33 34 int n; 35 int cntE, cntT; 36 char s[inf]; 37 int mem[inf]; 38 int top[inf]; 39 int dep[inf]; 40 int son[inf]; 41 int fa[inf]; 42 int size[inf]; 43 int id[inf]; 44 int val[inf]; 45 int head[inf << 1]; 46 struct Edge 47 int to; 48 int val; 49 int next; 50 e[inf << 1]; 51 struct Tree 52 int l; 53 int r; 54 int max; 55 int cov; 56 int add; 57 t[inf << 2]; 58 std::pair <int, int> p[inf]; 59 #define lson(a) (a) << 1 60 #define rson(a) (a) << 1 | 1 61 62 inline void AddEdge(int from, int to, int val) 63 ++cntE; 64 e[cntE].to = to; 65 e[cntE].val = val; 66 e[cntE].next = head[from]; 67 head[from] = cntE; 68 return; 69 70 71 inline int getVal(int now) 72 if(mem[now]) 73 return mem[now]; 74 for(int i = head[now]; i; i = e[i].next) 75 if(fa[now] == e[i].to) 76 return mem[now] = e[i].val; 77 78 return mem[now] = -INF; 79 80 81 void Dfs1(int now, int f, int depth) 82 fa[now] = f; 83 dep[now] = depth; 84 size[now] = 1; 85 int heavy = -INF; 86 for(int i = head[now]; i; i = e[i].next) 87 int to = e[i].to; 88 if(to == f) 89 continue; 90 Dfs1(to, now, depth + 1); 91 int y = size[to]; 92 size[now] += y; 93 if(y > heavy) 94 heavy = y; 95 son[now] = to; 96 97 98 return; 99 100 101 void Dfs2(int now, int point) 102 ++cntT; 103 top[now] = point; 104 id[now] = cntT; 105 val[cntT] = (now == 1 ? -INF : getVal(now)); 106 if(son[now] == 0) 107 return; 108 Dfs2(son[now], point); 109 for(int i = head[now]; i; i = e[i].next) 110 int to = e[i].to; 111 if(to == fa[now] || to == son[now]) 112 continue; 113 Dfs2(to, to); 114 115 return; 116 117 118 using std::max; 119 120 inline void updata(int now) 121 t[now].max = max (t[lson(now)].max , t[rson(now)].max); 122 return; 123 124 125 inline void pushtag(int now) 126 if(t[now].cov != -INF) 127 t[lson(now)].max = t[now].cov; 128 t[rson(now)].max = t[now].cov; 129 t[lson(now)].cov = t[now].cov; 130 t[rson(now)].cov = t[now].cov; 131 t[lson(now)].add = 0; 132 t[rson(now)].add = 0; 133 t[now].cov = -INF; 134 135 if(t[now].add != 0) 136 t[lson(now)].max += t[now].add; 137 t[rson(now)].max += t[now].add; 138 t[lson(now)].add += t[now].add; 139 t[rson(now)].add += t[now].add; 140 t[now].add = 0; 141 142 return; 143 144 145 void build(int now, int l, int r) 146 t[now].l = l; 147 t[now].r = r; 148 t[now].cov = -INF; 149 if(l == r) 150 t[now].max = val[l]; 151 return; 152 153 int mid = (l + r) >> 1; 154 build(lson(now), l, mid); 155 build(rson(now), mid + 1, r); 156 updata(now); 157 return; 158 159 void SgCover(int now, int l, int r, int k) 160 if(t[now].l >= l && t[now].r <= r) 161 t[now].cov = t[now].max = k; 162 t[now].add = 0; 163 return; 164 165 pushtag(now); 166 int mid = (t[now].l + t[now].r) >> 1; 167 if(l <= mid) 168 SgCover(lson(now), l, r, k); 169 if(r > mid) 170 SgCover(rson(now), l, r, k); 171 updata(now); 172 return; 173 174 175 void SgAdd(int now, int l, int r, int k) 176 if(t[now].l >= l && t[now].r <= r) 177 t[now].add += k; 178 t[now].max += k; 179 return; 180 181 pushtag(now); 182 int mid = (t[now].l + t[now].r) >> 1; 183 if(l <= mid) 184 SgAdd(lson(now), l, r, k); 185 if(r > mid) 186 SgAdd(rson(now), l, r, k); 187 updata(now); 188 return; 189 190 191 void SgChange(int now, int x, int k) 192 if(t[now].l > x || t[now].r < x) 193 return; 194 if(t[now].l == t[now].r) 195 t[now].max = k; 196 t[now].cov = -INF; 197 t[now].add = 0; 198 return; 199 200 pushtag(now); 201 int mid = (t[now].l + t[now].r) >> 1; 202 if(x <= mid) 203 SgChange(lson(now), x, k); 204 else 205 SgChange(rson(now), x, k); 206 updata(now); 207 return; 208 209 210 int SgQuery(int now, int l, int r) 211 if(t[now].l >= l && t[now].r <= r) 212 return t[now].max; 213 pushtag(now); 214 int mid = (t[now].l + t[now].r) >> 1; 215 int Max = -INF; 216 if(l <= mid) 217 Max = max (Max, SgQuery(lson(now), l, r)); 218 if(r > mid) 219 Max = max (Max, SgQuery(rson(now), l, r)); 220 return Max; 221 222 223 inline void cover(int a, int b, int k) 224 while(top[a] != top[b]) 225 if(dep[top[a]] < dep[top[b]]) 226 std::swap(a, b); 227 SgCover(1, id[top[a]], id[a], k); 228 a = fa[top[a]]; 229 230 if(a == b) 231 return; 232 if(dep[a] > dep[b]) 233 std::swap(a, b); 234 SgCover(1, id[a] + 1, id[b], k); 235 return; 236 237 238 inline void add(int a, int b, int k) 239 while(top[a] != top[b]) 240 if(dep[top[a]] < dep[top[b]]) 241 std::swap(a, b); 242 SgAdd(1, id[top[a]], id[a], k); 243 a = fa[top[a]]; 244 245 if(a == b) 246 return; 247 if(dep[a] > dep[b]) 248 std::swap(a, b); 249 SgAdd(1, id[a] + 1, id[b], k); 250 return; 251 252 253 inline int query(int a, int b) 254 int ans = -INF; 255 while(top[a] != top[b]) 256 if(dep[top[a]] < dep[top[b]]) 257 std::swap(a, b); 258 ans = max (ans, SgQuery(1, id[top[a]], id[a])); 259 a = fa[top[a]]; 260 261 if(a == b) 262 return ans; 263 if(dep[a] > dep[b]) 264 std::swap(a, b); 265 ans = max (ans, SgQuery(1, id[a] + 1, id[b])); 266 return ans; 267 268 269 inline int main() 270 n = read(); 271 for(int i = 1; i < n; i++) 272 p[i].first = read(); 273 p[i].second = read(); 274 int w = read(); 275 AddEdge(p[i].first, p[i].second, w); 276 AddEdge(p[i].second, p[i].first, w); 277 278 Dfs1(1, 0, 1); 279 Dfs2(1, 1); 280 build(1, 1, n); 281 while(true) 282 scanf("%s", s + 1); 283 if(s[1] == ‘S‘) 284 break; 285 int a = read(); 286 int b = read(); 287 if(s[2] == ‘a‘) 288 int ans = query(a, b); 289 printf("%d\n", ans == -INF ? 0 : ans); 290 else if(s[2] == ‘o‘) 291 cover(a, b, read()); 292 else if(s[2] == ‘h‘) 293 if(fa[p[a].first] == p[a].second) 294 SgChange(1, id[p[a].first], b); 295 else 296 SgChange(1, id[p[a].second],b); 297 else 298 add(a, b, read()); 299 300 return 0; 301 302 303 //namespace chino 304 305 signed main()return chino::main();
附:这题好难写啊 .. 可能是因为我太菜了 .. 很久以前就写过 ... 然后挂了0pts ... 实在不想调一个 350 行的程序 ... 后来今天重构了一遍 ... 不过还是依靠对拍 debug 了好几个小时 ... 码力不行啊 ...
以上是关于[luogu]月下“毛景树”:树 剖 好 题的主要内容,如果未能解决你的问题,请参考以下文章