目录
显示
题目链接
https://www.luogu.org/problem/P2146
题解
我们观察软件包的依赖树,很容易就可以转化题目给出的两种操作:
- 安装软件包 \(x\),相当于把从根节点到 \(x\) 上的所有节点设置为 \(1\)。
- 卸载软件包 \(x\),相当于把以 \(x\) 为根节点的子树的所有节点全部置 \(0\)。
于是这就是一道树链剖分板子题了。
#include <cstdio> #include <algorithm> using namespace std; struct edge { int v,next; }e[200005]; struct seg { int sum,tag; }s[400005]; int a[100005],head[100005],b[100005],cnte,cntp,n,q; int fa[100005],dep[100005],siz[100005],son[100005],top[100005],id[100005]; char str[15]; void addedge(int u,int v) { e[++cnte].v=v; e[cnte].next=head[u]; head[u]=cnte; } void dfs1(int u,int f,int d) { fa[u]=f; dep[u]=d; siz[u]=1; for(int i=head[u];i;i=e[i].next) if(e[i].v!=f) { dfs1(e[i].v,u,d+1); siz[u]+=siz[e[i].v]; if(siz[e[i].v]>siz[son[u]])son[u]=e[i].v; } } void dfs2(int u,int t) { top[u]=t; id[u]=++cntp; b[cntp]=a[u]; if(!son[u])return; dfs2(son[u],t); for(int i=head[u];i;i=e[i].next) if(e[i].v!=fa[u]&&e[i].v!=son[u])dfs2(e[i].v,e[i].v); } void pushup(int root) { s[root].sum=s[root<<1].sum+s[root<<1|1].sum; } void pushdown(int root,int l,int r) { if(s[root].tag==-1)return; int mid=(l+r)>>1; s[root<<1].tag=s[root].tag; s[root<<1|1].tag=s[root].tag; s[root<<1].sum=s[root].tag*(mid-l+1); s[root<<1|1].sum=s[root].tag*(r-mid); s[root].tag=-1; } void update(int root,int cl,int cr,int l,int r,int x) { if(r<cl||cr<l)return; if(l<=cl&&cr<=r) { s[root].sum=(cr-cl+1)*x; s[root].tag=x; return; } pushdown(root,cl,cr); int mid=(cl+cr)>>1; update(root<<1,cl,mid,l,r,x); update(root<<1|1,mid+1,cr,l,r,x); pushup(root); } void build(int root,int l,int r) { if(l==r) { s[root].tag=-1; return; } int mid=(l+r)>>1; build(root<<1,l,mid); build(root<<1|1,mid+1,r); } void update_path(int x,int y,int z) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); update(1,1,n,id[top[x]],id[x],z); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); update(1,1,n,id[x],id[y],z); } int main() { scanf("%d",&n); for(int i=2;i<=n;i++) { int x; scanf("%d",&x); x++; addedge(i,x); addedge(x,i); } dfs1(1,0,1); dfs2(1,1); build(1,1,n); scanf("%d",&q); for(int i=1;i<=q;i++) { int x; scanf("%s",str); if(str[0]=='i') { scanf("%d",&x); x++; int tmp=s[1].sum; update_path(1,x,1); printf("%d\n",s[1].sum-tmp); } else { scanf("%d",&x); x++; int tmp=s[1].sum; update(1,1,n,id[x],id[x]+siz[x]-1,0); printf("%d\n",tmp-s[1].sum); } } return 0; }