Linux用戶和OSX用戶必定對軟件包管理器不會陌生。經過軟件包管理器,你能夠經過一行命令安裝某一個軟件包,而後軟件包管理器會幫助你從軟件源下載軟件包,同時自動解決全部的依賴(即下載安裝這個軟件包的安裝所依賴的其它軟件包),完成全部的配置。Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是優秀的軟件包管理器。spa
你決定設計你本身的軟件包管理器。不可避免地,你要解決軟件包之間的依賴問題。若是軟件包A依賴軟件包B,那麼安裝軟件包A之前,必須先安裝軟件包B。同時,若是想要卸載軟件包B,則必須卸載軟件包A。如今你已經得到了全部的軟件包之間的依賴關係。並且,因爲你以前的工做,除0號軟件包之外,在你的管理器當中的軟件包都會依賴一個且僅一個軟件包,而0號軟件包不依賴任何一個軟件包。依賴關係不存在環(如有m(m≥2)個軟件包A1,A2,A3,⋯,Am,其中A1依賴A2,A2依賴A3,A3依賴A4,……,A[m-1]依賴Am,而Am依賴A1,則稱這m個軟件包的依賴關係構成環),固然也不會有一個軟件包依賴本身。設計
如今你要爲你的軟件包管理器寫一個依賴解決程序。根據反饋,用戶但願在安裝和卸載某個軟件包時,快速地知道這個操做實際上會改變多少個軟件包的安裝狀態(即安裝操做會安裝多少個未安裝的軟件包,或卸載操做會卸載多少個已安裝的軟件包),你的任務就是實現這個部分。注意,安裝一個已安裝的軟件包,或卸載一個未安裝的軟件包,都不會改變任何軟件包的安裝狀態,即在此狀況下,改變安裝狀態的軟件包數爲0。code
然而能夠直接樹剖homebrew
對於安裝軟件,就把根到它的路徑所有設爲\(1\)ip
從該點一直跳到根,邊跳邊線段樹區間修改get
對於卸載軟件,就把它和它的子樹所有設爲\(0\)string
這個一次線段樹區間修改就能夠了io
操做先後不一樣的的數個數,能夠拿操做先後的整棵樹裏的\(1\)的數目相減獲得ast
#pragma GCC optimize("O3") #pragma G++ optimize("O3") #include<stdio.h> #include<string.h> #define MAXN 100005 #define ll long long #define reg register ll #define fo(i,a,b) for (reg i=a;i<=b;++i) #define fd(i,a,b) for (reg i=a;i>=b;--i) #define rep(i,a) for (reg i=last[a];i;i=next[i]) using namespace std; ll last[MAXN],next[MAXN],tov[MAXN]; ll fa[MAXN],top[MAXN],size[MAXN],depth[MAXN],heavy_son[MAXN]; ll tr[MAXN<<2],bz[MAXN<<2],to_tree[MAXN],to_num[MAXN]; ll n,q,tot; char s[10]; inline ll read() { ll x=0,f=1;char ch=getchar(); while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();} while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar(); return x*f; } inline ll abs(ll x){return x>0?x:-x;} inline void link(ll x,ll y){next[++tot]=last[x],last[x]=tot,tov[tot]=y;} inline void dfs1(ll x) { rep(i,x) { depth[tov[i]]=depth[x]+1,size[tov[i]]=1,dfs1(tov[i]),size[x]+=size[tov[i]]; if (size[tov[i]]>size[heavy_son[x]])heavy_son[x]=tov[i]; } } inline void dfs2(ll x,ll y) { if (!x)return;top[x]=y; to_tree[x]=++tot,to_num[tot]=x,dfs2(heavy_son[x],y); rep(i,x)if (tov[i]!=heavy_son[x])dfs2(tov[i],tov[i]); } inline void maketree(ll t,ll l,ll r) { bz[t]=-1;if (l==r)return; ll mid=(l+r)>>1;maketree(t<<1,l,mid),maketree((t<<1)+1,mid+1,r); } inline void downdata(ll t,ll l,ll r) { if (bz[t]==-1)return;ll mid=(l+r)>>1; tr[t<<1]=(mid-l+1)*bz[t],tr[(t<<1)+1]=(r-mid)*bz[t]; bz[t<<1]=bz[(t<<1)+1]=bz[t],bz[t]=-1; } inline void tree_modify(ll t,ll l,ll r,ll x,ll y,ll z) { if (l==x && y==r){tr[t]=(r-l+1)*z,bz[t]=z;return;} ll mid=(l+r)>>1;downdata(t,l,r); if (y<=mid)tree_modify(t<<1,l,mid,x,y,z); else if (x>mid)tree_modify((t<<1)+1,mid+1,r,x,y,z); else tree_modify(t<<1,l,mid,x,mid,z),tree_modify((t<<1)+1,mid+1,r,mid+1,y,z); tr[t]=tr[t<<1]+tr[(t<<1)+1]; } inline void modify(ll x) { while (top[x]!=1)tree_modify(1,1,n,to_tree[top[x]],to_tree[x],1),x=fa[top[x]]; tree_modify(1,1,n,1,to_tree[x],1); } int main() { //freopen("P2146.in","r",stdin); freopen("manager.in","r",stdin); freopen("manager.out","w",stdout); n=read();fo(i,2,n)link(fa[i]=read()+1,i); tot=0,dfs1(depth[1]=size[1]=1), dfs2(1,1),maketree(1,1,n),q=read(); while (q--) { scanf("%s",&s);ll x=read()+1,tmp=tr[1]; if (s[0]=='i') { modify(x),printf("%lld\n",abs(tr[1]-tmp)); continue; } tree_modify(1,1,n,to_tree[x],to_tree[x]+size[x]-1,0); printf("%lld\n",abs(tr[1]-tmp)); } return 0; }