洛谷 2146 [NOI2015]软件包管理器
【题解】
每个软件只依赖另一个软件,且依赖关系不构成环,那么很容易想到这是树形结构。
我们用1表示以安装,用0表示未安装或已卸载;那么安装一个软件,就是把它到树根的路径上所有的点都改为1;卸载一个软件,就是把它的子树全部改为0.
状态改变的软件包数就是操作前后整棵树的点权和。
这样我们直接树链剖分即可。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 #define LL long long 6 #define rg register 7 #define N 100010 8 #define ls (u<<1) 9 #define rs (u<<1|1) 10 #define mid ((a[u].l+a[u].r)>>1) 11 #define len(x) (a[x].r-a[x].l+1) 12 using namespace std; 13 int n,m,cnt,last,fa[N],hvy[N],top[N],dep[N],siz[N],dfn[N]; 14 vector<int>son[N]; 15 struct tree{ 16 int l,r,sum; bool mark; 17 }a[N<<2]; 18 inline int read(){ 19 int k=0,f=1; char c=getchar(); 20 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 21 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 22 return k*f; 23 } 24 void dfs1(int x){ 25 siz[x]=1; 26 for(rg int i=0,to;i<son[x].size();i++){ 27 dfs1(to=son[x][i]); siz[x]+=siz[to]; 28 if(siz[to]>siz[hvy[x]]) hvy[x]=to; 29 } 30 } 31 void dfs2(int x,int tp){ 32 top[x]=tp; dfn[x]=++cnt; 33 if(hvy[x]) dfs2(hvy[x],tp); 34 for(rg int i=0,to;i<son[x].size();i++) 35 if((to=son[x][i])!=hvy[x]) dfs2(to,to); 36 } 37 void build(int u,int l,int r){ 38 a[u].l=l; a[u].r=r; 39 if(l<r) build(ls,l,mid),build(rs,mid+1,r); 40 } 41 inline void pushdown(int u){ 42 a[u].mark=0; a[ls].mark=a[rs].mark=1; 43 if(a[u].sum) a[ls].sum=len(ls),a[rs].sum=len(rs); 44 else a[ls].sum=a[rs].sum=0; 45 } 46 void update(int u,int l,int r,bool type){//type==1-->install 47 if(l<=a[u].l&&a[u].r<=r){ 48 a[u].sum=type?len(u):0; 49 a[u].mark=1; 50 return; 51 } 52 if(a[u].mark) pushdown(u); 53 if(l<=mid) update(ls,l,r,type); 54 if(r>mid) update(rs,l,r,type); 55 a[u].sum=a[ls].sum+a[rs].sum; 56 } 57 //int query(int u,int l,int r){ 58 // if(l<=a[u].l&&a[u].r<=r) return a[u].sum; 59 // if(a[u].mark) pushdown(u); int ret=0; 60 // if(l<=mid) ret=query(ls,l,r); 61 // if(r>mid) ret+=query(rs,l,r); 62 // return ret; 63 //} 64 int main(){ 65 n=read(); 66 for(rg int i=2;i<=n;i++){ 67 int f=read()+1; 68 fa[i]=f; dep[i]=dep[f]+1; 69 son[f].push_back(i); 70 } 71 dfs1(1); dfs2(1,1); build(1,1,n); 72 // for(rg int i=1;i<=n;i++) printf("%d ",siz[i]); puts("siz"); 73 m=read(); 74 while(m--){ 75 char c=getchar(); while(c!='i'&&c!='u') c=getchar(); 76 int x=read()+1; 77 if(c=='i'){ 78 int t=top[x]; 79 while(x){ 80 update(1,dfn[t],dfn[x],1); 81 x=fa[t]; t=top[x]; 82 } 83 } 84 else update(1,dfn[x],dfn[x]+siz[x]-1,0); 85 printf("%d\n",abs(a[1].sum-last),a[1].sum); last=a[1].sum; 86 } 87 return 0; 88 }