bzoj 4196:[NOI2015] 软件包管理器 (树链剖分)
Posted cminus
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 4196:[NOI2015] 软件包管理器 (树链剖分)相关的知识,希望对你有一定的参考价值。
---恢复内容开始---
第一次做树剖
找同学要了模板 + 各种借鉴
先用dfs在划分轻重链并编号, install的时候就从查询的节点到根寻找标记的点有多少个,再用深度减去标记的点的个数,并把路径上所有点都标记
uninstall就是搜索查询的点的子树的标记个数,并取消所有的标记。
代码如下
1 /************************************************************** 2 Problem: 4196 3 Language: C++ 4 Result: Accepted 5 Time:8312 ms 6 Memory:7416 kb 7 ****************************************************************/ 8 9 #include <cstdio> 10 #include <vector> 11 #include <cstring> 12 using namespace std; 13 #define g(l, r) (l + r | l != r) 14 #define o g(l, r) 15 #define ls g(l, mid) 16 #define rs g(mid + 1, r) 17 const int N = 100100; 18 19 int n, dep[N], fa[N], hs[N], size[N], top[N], pos[N], mark[N<<1], sum[N<<1], tot, L, R, m; 20 vector < int > edge[N]; 21 22 inline void dfs1(int u, int d, int f){ 23 dep[u] = d; fa[u] = f; hs[u] = -1; size[u] = 1; 24 int tmp = 0; 25 for (int i = 0; i < edge[u].size(); i++){ 26 int &v = edge[u][i]; 27 dfs1(v, d + 1, u); 28 if (size[v] > tmp) 29 hs[u] = v, tmp = size[v]; 30 size[u] += size[v]; 31 } 32 } 33 34 inline void dfs2(int u, int T){ 35 top[u] = T; pos[u] = ++tot; 36 if (hs[u] == -1) return ; 37 dfs2(hs[u], T); 38 for (int i = 0; i < edge[u].size(); i++){ 39 int &v = edge[u][i]; 40 if (hs[u] == v) continue; 41 dfs2(v, v); 42 } 43 } 44 45 inline void push(int l, int r) { 46 if (mark[o] == -1) return; 47 int mid = l + r >> 1; 48 if (l < r) { 49 mark[ls] = mark[o]; 50 sum[ls] = mark[o] * (mid - l + 1); 51 mark[rs] = mark[o]; 52 sum[rs] = mark[o] * (r - (mid + 1) + 1); 53 } 54 mark[o] = -1; 55 } 56 57 void modify(int l, int r){ 58 if (L <= l && r <= R){ 59 sum[o] = m * (r - l + 1); 60 mark[o] = m; 61 return ; 62 } 63 push(l, r); 64 int mid = l + r >> 1; 65 if (L <= mid) modify(l, mid); 66 if (R >= mid + 1) modify(mid + 1, r); 67 sum[o] = sum[ls] + sum[rs]; 68 } 69 70 int getSum(int l, int r){ 71 if (L <= l && r <= R){ 72 return sum[o]; 73 } 74 push(l, r); 75 int mid = l + r >> 1, ans = 0; 76 if (L <= mid) ans += getSum(l, mid); 77 if (R >= mid + 1) ans += getSum(mid + 1, r); 78 return ans; 79 } 80 81 inline void install(int u){ 82 int f = top[u], ans = dep[u]; 83 m = 1; 84 while(f){ 85 L = pos[f], R = pos[u]; 86 ans -= getSum(1, tot); 87 modify(1, tot); 88 u = fa[f]; f = top[u]; 89 } 90 L = pos[f], R = pos[u]; 91 ans -= getSum(1, tot); 92 modify(1, tot); 93 printf("%d\n", ans); 94 } 95 96 inline void uninstall(int u){ 97 L = pos[u], R = pos[u] + size[u] - 1, m = 0; 98 int ans = getSum(1, tot); 99 modify(1, tot); 100 printf("%d\n", ans); 101 } 102 103 int main(){ 104 scanf("%d", &n); 105 for (int i = 1; i < n; i++){ 106 int x; scanf("%d", &x); 107 edge[x].push_back(i); 108 } 109 dfs1(0, 1, -1); dfs2(0, 0); 110 int q; 111 scanf("%d", &q); 112 memset(mark, 0xff, sizeof(mark)); 113 while(q--){ 114 char str[15]; int x; 115 scanf("%s%d", str, &x); 116 if (*str == ‘i‘) install(x); 117 else uninstall(x); 118 } 119 return 0; 120 }
以上是关于bzoj 4196:[NOI2015] 软件包管理器 (树链剖分)的主要内容,如果未能解决你的问题,请参考以下文章
Bzoj 4196: [Noi2015]软件包管理器 树链剖分
[UOJ#128][BZOJ4196][Noi2015]软件包管理器