题解
-
很容易发现,改变了某个软件,变的只会是该软件到根的距离+路径上所有软件的子树
- 那么我们怎么快速求出这个东东,安装时,考虑将x到根的路径上全部变为1,然后用线段树维护区间和用改变后-改变前就是答案
- 卸载的话,就将x到根的路径全部变成0,也是区间和,用改变前-改变后
- 区间和的话就可以用线段树来维护
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #define N 100010 5 using namespace std; 6 struct edge {int to,from;}e[N*2]; 7 struct tree {int lson,rson,tag,sum;}t[N*4]; 8 int n,q,tot,cnt,dfn[N],head[N],pos[N],top[N],fa[N],deep[N],size[N],son[N]; 9 char s[10]; 10 void insert(int x,int y) { e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt; } 11 void dfs1(int x) 12 { 13 size[x]=1,deep[x]=deep[fa[x]]+1; 14 for (int i=head[x];i;i=e[i].from) if (e[i].to!=fa[x]) 15 { 16 dfs1(e[i].to),size[x]+=size[e[i].to]; 17 if (size[e[i].to]>size[son[x]]) son[x]=e[i].to; 18 } 19 } 20 void dfs2(int x,int pre) 21 { 22 dfn[x]=++tot,pos[dfn[x]]=x,top[x]=pre; 23 if (son[x]) dfs2(son[x],pre); 24 for (int i=head[x];i;i=e[i].from) if (e[i].to!=fa[x]&&e[i].to!=son[x]) dfs2(e[i].to,e[i].to); 25 } 26 void build(int d,int l,int r) 27 { 28 t[d].lson=l,t[d].rson=r,t[d].sum=0,t[d].tag=-1; 29 if (l==r) return; 30 int mid=l+r>>1; 31 build(d*2,l,mid),build(d*2+1,mid+1,r); 32 } 33 void pushdown(int d) 34 { 35 t[d*2].sum=(t[d*2].rson-t[d*2].lson+1)*t[d].tag,t[d*2+1].sum=(t[d*2+1].rson-t[d*2+1].lson+1)*t[d].tag, 36 t[d*2].tag=t[d*2+1].tag=t[d].tag,t[d].tag=-1; 37 } 38 void update(int d,int l,int r,int k) 39 { 40 if (t[d].rson<l||t[d].lson>r) return; 41 if (t[d].rson<=r&&t[d].lson>=l) { t[d].sum=(t[d].rson-t[d].lson+1)*k,t[d].tag=k; return; } 42 if (t[d].tag!=-1) pushdown(d); 43 update(d*2,l,r,k),update(d*2+1,l,r,k),t[d].sum=t[d*2].sum+t[d*2+1].sum; 44 } 45 void change(int x,int y,int k) 46 { 47 while (top[x]!=top[y]) 48 { 49 if (deep[top[x]]<deep[top[y]]) swap(x,y); 50 update(1,dfn[top[x]],dfn[x],k),x=fa[top[x]]; 51 } 52 if (deep[x]>deep[y]) swap(x,y); 53 update(1,dfn[x],dfn[y],k); 54 } 55 int main() 56 { 57 scanf("%d",&n); 58 for (int i=2;i<=n;i++) scanf("%d",&fa[i]),fa[i]++,insert(fa[i],i); 59 dfs1(1),dfs2(1,1),build(1,1,tot); 60 scanf("%d",&q); 61 for (int x,sum;q;q--) 62 { 63 scanf("%s%d",s+1,&x),x++,sum=t[1].sum; 64 if (s[1]=='i') change(1,x,1),printf("%d ",abs(sum-t[1].sum)); 65 else update(1,dfn[x],dfn[x]+size[x]-1,0),printf("%d ",abs(sum-t[1].sum)); 66 } 67 }