BZOJ4196 [NOI2015] 软件包管理器
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4196,http://uoj.ac/problem/128
Description
Linux用户和OSX用户一定对软件包管理器不会陌生。通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置。Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器。
你决定设计你自己的软件包管理器。不可避免地,你要解决软件包之间的依赖问题。如果软件包A依赖软件包B,那么安装软件包A以前,必须先安装软件包B。同时,如果想要卸载软件包B,则必须卸载软件包A。现在你已经获得了所有的软件包之间的依赖关系。而且,由于你之前的工作,除0号软件包以外,在你的管理器当中的软件包都会依赖一个且仅一个软件包,而0号软件包不依赖任何一个软件包。依赖关系不存在环(若有m(m≥2)个软件包A1,A2,A3,…,Am,其中A1依赖A2,A2依赖A3,A3依赖A4,……,Am−1依赖Am,而Am依赖A1,则称这m个软件包的依赖关系构成环),当然也不会有一个软件包依赖自己。
现在你要为你的软件包管理器写一个依赖解决程序。根据反馈,用户希望在安装和卸载某个软件包时,快速地知道这个操作实际上会改变多少个软件包的安装状态(即安装操作会安装多少个未安装的软件包,或卸载操作会卸载多少个已安装的软件包),你的任务就是实现这个部分。注意,安装一个已安装的软件包,或卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为0。
Input
输入文件的第1行包含1个正整数n,表示软件包的总数。软件包从0开始编号。
随后一行包含n−1个整数,相邻整数之间用单个空格隔开,分别表示1,2,3,…,n−2,n−1号软件包依赖的软件包的编号。
接下来一行包含1个正整数q,表示询问的总数。
之后q行,每行1个询问。询问分为两种:
installx:表示安装软件包x
uninstallx:表示卸载软件包x
你需要维护每个软件包的安装状态,一开始所有的软件包都处于未安装状态。对于每个操作,你需要输出这步操作会改变多少个软件包的安装状态,随后应用这个操作(即改变你维护的安装状态)。
Output
输出文件包括q行。
输出文件的第i行输出1个整数,为第i步操作中改变安装状态的软件包数。
听说这是NOI题目?水水的树链剖分
建立一棵有向树,边由被依赖的软件包指向依赖的软件包
安装一个软件包就从根到这个点的一条链全部改为1,卸载一个软件包就把它的子树全部改为0
根据DFS序的性质,如果一个点在线段树上的编号为 pos[x],子树的最后一个节点的编号就为 pos[x] + size[x] - 1,在线段树上这棵子树是连续的一个区间
软件包的编号从0开始,所以对所有的点都加了一个偏移量1
第一次交的时候打成了 pos[x + size[x] - 1],导致了RE,还有其他的一些bug,出现后从UOJ上找来样例数据
BZOJ的数据太夸张了,UOJ才3317ms
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #define rep(i,l,r) for(int i=l; i<=r; i++) 6 #define clr(x,y) memset(x,y,sizeof(x)) 7 #define travel(x) for(Edge *p=last[x]; p; p=p->pre) 8 using namespace std; 9 const int INF = 0x3f3f3f3f; 10 const int maxn = 100010; 11 inline int read(){ 12 int ans = 0, f = 1; 13 char c = getchar(); 14 for(; !isdigit(c); c = getchar()) 15 if (c == '-') f = -1; 16 for(; isdigit(c); c = getchar()) 17 ans = ans * 10 + c - '0'; 18 return ans * f; 19 } 20 struct Edge{ 21 Edge *pre; int to; 22 }edge[maxn<<1]; 23 Edge *last[maxn], *pt = edge; 24 struct Node{ 25 int l,r,v,t; 26 }t[maxn<<2]; 27 int n,m,x,y,q,segnum=0,dep[maxn],top[maxn],size[maxn],fa[maxn],pos[maxn]; 28 char ch[10]; 29 inline void addedge(int x,int y){ 30 pt->pre = last[x]; pt->to = y; last[x] = pt++; 31 } 32 void dfs(int x){ 33 size[x] = 1; 34 travel(x){ 35 dep[p->to] = dep[x] + 1; 36 fa[p->to] = x; 37 dfs(p->to); 38 size[x] += size[p->to]; 39 } 40 } 41 void dfs(int x,int chain){ 42 pos[x] = ++segnum; top[x] = chain; 43 int k = 0; 44 travel(x){ 45 if (size[p->to] > size[k]) k = p->to; 46 } 47 if (!k) return; 48 dfs(k,chain); 49 travel(x){ 50 if (p->to != k) dfs(p->to,p->to); 51 } 52 } 53 void build(int u,int v,int w){ 54 t[w].l = u; t[w].r = v; t[w].v = 0; t[w].t = -1; 55 if (u == v) return; 56 int mid = (u + v) >> 1; 57 build(u,mid,w<<1); build(mid+1,v,w<<1|1); 58 } 59 inline void pushdown(int w){ 60 if (t[w].l == t[w].r || t[w].t == -1) return; 61 t[w<<1].t = t[w<<1|1].t = t[w].t; 62 t[w<<1].v = (t[w<<1].r - t[w<<1].l + 1) * t[w].t; 63 t[w<<1|1].v = (t[w<<1|1].r - t[w<<1|1].l + 1) * t[w].t; 64 t[w].t = -1; 65 } 66 inline void maintain(int w){ 67 t[w].v = t[w<<1].v + t[w<<1|1].v; 68 } 69 void modify(int u,int v,int w,int x){ 70 pushdown(w); 71 if (t[w].l == u && t[w].r == v){ 72 t[w].v = x * (v - u + 1); 73 t[w].t = x; return; 74 } 75 int mid = (t[w].l + t[w].r) >> 1; 76 if (v <= mid) modify(u,v,w<<1,x); 77 else if (u > mid) modify(u,v,w<<1|1,x); 78 else{ 79 modify(u,mid,w<<1,x); 80 modify(mid+1,v,w<<1|1,x); 81 } 82 maintain(w); 83 } 84 int query(int u,int v,int w){ 85 pushdown(w); 86 if (t[w].l == u && t[w].r == v) return t[w].v; 87 int mid = (t[w].l + t[w].r) >> 1; 88 if (v <= mid) return query(u,v,w<<1); 89 else if (u > mid) return query(u,v,w<<1|1); 90 else return query(u,mid,w<<1) + query(mid+1,v,w<<1|1); 91 } 92 int install(int x,int y){ 93 int ret = 0; 94 while (top[x] != top[y]){ 95 if (dep[top[x]] < dep[top[y]]) swap(x,y); 96 ret += query(pos[top[x]],pos[x],1); 97 modify(pos[top[x]],pos[x],1,1); 98 x = fa[top[x]]; 99 } 100 if (dep[x] < dep[y]) swap(x,y); 101 ret += query(pos[y],pos[x],1); 102 modify(pos[y],pos[x],1,1); 103 return ret; 104 } 105 int uninstall(int x){ 106 int ret = query(pos[x],pos[x]+size[x]-1,1); 107 modify(pos[x],pos[x]+size[x]-1,1,0); 108 return ret; 109 } 110 int main(){ 111 n = read(); clr(last,0); 112 rep(i,1,n-1){ 113 x = read(); 114 addedge(x+1,i+1); 115 } 116 dep[1] = 0; dfs(1); dfs(1,1); build(1,n,1); 117 q = read(); 118 rep(i,1,q){ 119 scanf("%s",ch); x = read() + 1; 120 if (ch[0] == 'i') printf("%d\n",dep[x] + 1 - install(1,x)); 121 else printf("%d\n",uninstall(x)); 122 } 123 return 0; 124 }