[NOI2015] Package Manager time limit:10 Sec Memory limit:512 MB
submit:331 solved:199
[Submit] [Status] [Discuss] Description
Linux users and OSX users must not be unfamiliar with the package manager. With the Package Manager, you can install a package from a single line of commands, and then the Package Manager will help you download the package from the software source, and automatically resolve all dependencies (that is, other packages that are dependent on downloading the installation of this package) to complete all configurations. The Apt-get,fedora/centos used by Debian/ubuntu and the homebrew available under OSX are excellent package managers.
You decide to design your own package Manager. Inevitably, you need to solve the dependencies between packages. If package a relies on package B, you must install package B before you install package A. Also, if you want to uninstall package B, you must uninstall package a. Now you've got all the dependencies between the packages. And, because of your previous work, in addition to the No. 0 package, the packages in your manager will depend on one and only one package, and the No. 0 package does not depend on any one package. Dependency does not exist ring (if there is M (m≥2) package a1,a2,a3,..., am, where A1 relies on a2,a2 dependency a3,a3 dependency a4,......,am−1 dependent am, and am relies on A1, it is said that the dependencies of M packages form a ring), Of course there will not be a package that relies on itself. Now you need to write a dependency resolver for your package manager. Based on feedback, users want to quickly know when a package is installed and uninstalled how many packages are installed (that is, how many packages are installed, or how many installed packages are uninstalled), and your task is to implement this section. Note that installing an installed package, or uninstalling a package that is not installed, will not change the installation state of any packages, in which case the number of packages changing the installation state is 0. Input
The 1th line of the input file contains 1 positive integer n, which indicates the total number of packages. The package is numbered starting from 0.
The following line contains n−1 integers, separated by a single space between adjacent integers, representing the number of packages on which the,..., n−2,n−1 package depends. The next line contains 1 positive integer q, which indicates the total number of queries. After Q line, 1 queries per line. There are two types of queries: INSTALLX: Indicates the installation package XUNINSTALLX: Uninstall package x you need to maintain the installation state of each package, and all packages are not installed at the beginning. For each operation, you need to output this step to change the installation state of how many packages, and then apply this action (that is, change the installation state of your maintenance). Output
The output file includes the Q line.
The output file of line I outputs 1 integers, the number of packages that change the installation state for step I operations. Sample Input7
0 0 0 1 1 5
5
Install 5
Install 6
Uninstall 1
Install 4
Uninstall 0Sample Output3
1
3
2
3HINT
All packages are not installed at the beginning.
Installing the 5th package requires the installation of 0,1,5 three packages.
After installing the 6th package, you only need to install the number 6th package. 0,1,5,6 Four packages are installed at this time.
Uninstalling the 1th package requires uninstalling 1,5,6 three packages. Only the No. 0 package is in the installation state at this time.
After installing the 4th package, you need to install 1, 42 packages. At this point the 0,1,4 is in the installation state.
Finally, uninstalling the NO. 0 package will uninstall all packages.
n=100000
q=100000
Source
At first, I wanted to use a tree chain, but there was no better way to think about it (the complexity of programming).
And then decisively abandon ...
The problem is actually a tree.
Add points to the line tree, and then install the process is to install the ancestors of the current package, in fact, is the tree chain to modify the split. And the unloading process is to unload the tree.
Now for the following code to explain:
The top record is the chain header of the current node's heavy chain.
Son records the number of nodes (including itself) of the current subtree.
A is the father of the current node (0 of the father is-1)
BW represents the heavy path of the current node.
As for Cntv and Vis is a line tree maintenance of things, CNTV is to count the current interval how many packages unloaded, Vis is marked, 1 mark this interval has all installed, 0 indicates that the interval is not installed, 1 is not marked.
#include <cstdio>#include<cstring>#include<algorithm>using namespacestd;Const intMAXN =100005; structedge{intx, y, next; Edge () {} Edge (intUintv): X (U), Y (v) {}}EDGES[MAXN]; intTOP[MAXN], SON[MAXN], BW[MAXN], FIRST[MAXN], A[MAXN], NUM[MAXN];intCNTV[MAXN <<2], VIS[MAXN <<2];inttots, N, M, X, T;voidAddintUintv) {Edges[tots]=Edge (U, v); Edges[tots].next=First[u]; First[u]= tots++;} voidDFS1 (intx) { intWeight =0; SON[X]=1; for(inti = first[x]; I! =-1; i =Edges[i].next) {DFS1 (EDGES[I].Y); if(Son[edges[i].y] >weight) {Bw[x]=i; Weight=SON[EDGES[I].Y]; } Son[x]+=SON[EDGES[I].Y]; }} voidDFS2 (intXintf) {Top[x]=Top[f]; NUM[X]= ++T; if(first[x]! =-1) DFS2 (EDGES[BW[X]].Y, x); for(inti = first[x]; I! =-1; i =edges[i].next)if(Bw[x]! =i) {TOP[EDGES[I].Y]=edges[i].y; DFS2 (EDGES[I].Y, EDGES[I].Y); }} voidPushdown (into) { intLC = O <<1, rc = LC +1; if(Vis[o] >=0) {VIS[LC]= VIS[RC] =Vis[o]; Vis[o]= -1; }} voidMaintain (intOintLintR) { if(Vis[o] >0) Cntv[o] =0; ElseCntv[o] = r-l +1; if(L < R && Vis[o] = =-1) { intLC = O <<1, rc = LC +1; Cntv[o]= CNTV[LC] +CNTV[RC]; }} voidUpdateintOintLintRintY1,intY2,intval) { if(Y1 <= L && R <=y2) {Vis[o]=Val; Maintain (o, L, R); return; } pushdown (o); intMid = (L + R) >>1; intLC = O <<1, rc = LC +1; if(Mid >=y1) Update (LC, L, Mid, Y1, Y2, Val); ElseMaintain (LC, L, mid); if(Mid +1<= y2) update (RC, Mid +1, R, Y1, Y2, Val); ElseMaintain (RC, Mid +1, R); Maintain (o, L, R);} intQueryintOintLintRintY1,inty2) { if(Vis[o] >=0) { intL =Max (L, y1); intR =min (R, y2); if(Vis[o] >0)return 0; Else returnR-l +1; } if(Y1 <= L && R <=y2) { returnCntv[o]; } intMid = (L + R) >>1; intLC = O <<1, rc = LC +1, sum =0; if(Mid >= y1) sum + =Query (LC, L, Mid, Y1, y2); if(Mid +1<= y2) sum + = query (RC, Mid +1, R, Y1, y2); returnsum;} intMain () {scanf ("%d", &N); memset (First,-1,sizeof(first)); Tots=0; a[0] = -1; for(inti =1; I < n; ++i) {scanf ("%d", &A[i]); Add (A[i], i); } memset (son,0,sizeof(son)); DFS1 (0); T=0; top[0] =0; DFS2 (0,0); scanf ("%d", &m); memset (CNTV,0,sizeof(CNTV)); memset (Vis,0,sizeof(VIS)); Update (1,1N1N0); while(m--) { Charcmd[ -]; scanf ("%s%d", CMD, &x); if(cmd[0] =='I') { intF, sum =0; Do{f=Top[x]; Sum+ = Query (1,1, N, Num[f], num[x]); Update (1,1, N, Num[f], num[x],1); X=A[f]; } while(X! =-1); printf ("%d\n", sum); } Else{printf ("%d\n", Son[x]-query (1,1, N, Num[x], num[x] + son[x]-1)); Update (1,1, N, Num[x], num[x] + son[x]-1,0); } } return 0;}
"Bzoj 4196" [Noi2015] Package Manager