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 } 
时间: 2024-08-26 04:02:40

bzoj 4196:[NOI2015] 软件包管理器 (树链剖分)的相关文章

Bzoj 4196: [Noi2015]软件包管理器 树链剖分

4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 721  Solved: 419[Submit][Status][Discuss] Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian

[Bzoj4196] [NOI2015] 软件包管理器 [树链剖分,线段树]

题解摘要:树链剖分后用线段树区间查询修改,对于安装软件,将改点到根的路径全部变为1,对于卸载软件,将子树清空.注意边界,编号是从0开始的,容易漏掉树根. 第一次写树剖- 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cmath> 7 #inclu

bzoj4196 [Noi2015]软件包管理器——树链剖分

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4196 树链剖分. 代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; int const maxn=1e5+5; int n,m,fa[maxn],dfn[maxn],end[maxn],top[maxn],to[maxn],siz[maxn],head[

BZOJ 4196: [Noi2015]软件包管理器

二次联通门 : BZOJ 4196: [Noi2015]软件包管理器 /* BZOJ 4196: [Noi2015]软件包管理器 树链剖分 树链剖分 , 用线段树维护链上的和与子树的和 对于1操作, 每次预先查询待修改点x点的深度 后查询1到x这条链上有多少已安装的, 然后上面的值减下面的值 对于2操作,每次查询以x为根的子树的大小 修改整颗子树即可.. 说白了其实就是板子题 */ #include <cstdio> #define Max 500090 inline int min (int

【树链剖分】【NOI 2015】【bzoj 4196】软件包管理器

4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 122 Solved: 97 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/Ce

4196: [Noi2015]软件包管理器

Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 412  Solved: 251[Submit][Status][Discuss] Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedo

【BZOJ 4196】[Noi2015]软件包管理器

[Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 331  Solved: 199[Submit][Status][Discuss] Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubunt

洛谷 P2146 [NOI2015]软件包管理器 (树链剖分模板题)

题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器. 你决定设计你自己的软件包管理器.不可避免地,你要解决软件包之间的依赖问题.如果软件包A依赖软件包B,那

BZOJ_4196_[Noi2015]软件包管理器_树链剖分

题意: Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器. 你决定设计你自己的软件包管理器.不可避免地,你要解决软件包之间的依赖问题.如果软件包A依赖软件包B,那么

BZOJ4196 [NOI2015] 软件包管理器

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4196,http://uoj.ac/problem/128 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/Cen