[树链剖分][线段树] Luogu P2146 软件包管理器
Posted comfortable
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[树链剖分][线段树] Luogu P2146 软件包管理器相关的知识,希望对你有一定的参考价值。
题解
-
很容易发现,改变了某个软件,变的只会是该软件到根的距离+路径上所有软件的子树
- 那么我们怎么快速求出这个东东,安装时,考虑将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\\n",abs(sum-t[1].sum)); 65 else update(1,dfn[x],dfn[x]+size[x]-1,0),printf("%d\\n",abs(sum-t[1].sum)); 66 67
以上是关于[树链剖分][线段树] Luogu P2146 软件包管理器的主要内容,如果未能解决你的问题,请参考以下文章
Luogu2542 AHOI2005 航线规划 树链剖分线段树