zoukankan      html  css  js  c++  java
  • [NOI2015] 软件包管理器

    Luogu
    LOJ

    题目大意

    有一颗依赖关系构成的一颗树,有两个操作

    1. install ,把从 x 到根节点这一条链全都改为 1
    2. uninstall ,把以 x 为根的子树全都变成 0
      现在求每个操作会改变多少节点的值

    题解

    标准树剖,但是细节很多

    1. 懒标记开始为 -1,下传后也要变成 -1
    2. 聪明的做法:先记录操作之前 1 的个数,在查询操作后的个数,然后输出差值

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100005;
    int n,T,lst[N],nxt[N<<1],to[N<<1],cnt,odd,dfn[N],sz[N],top[N],dep[N],fa[N],son[N],sm[N<<3],tg[N<<3];
    inline void Ae(int fr,int go) { to[++cnt]=go,nxt[cnt]=lst[fr],lst[fr]=cnt; }
    char opt[15];
    void Get(int u,int f) {
    	sz[u]=1,dep[u]=dep[fa[u]=f]+1;
    	for(int i=lst[u];i;i=nxt[i])
    		if(to[i]^f) {
    			Get(to[i],u),sz[u]+=sz[to[i]];
    			if(sz[to[i]]>sz[son[u]])son[u]=to[i];
    		}
    }
    void Dfs(int u,int nw) {
    	top[u]=nw,dfn[u]=++odd;
    	if(!son[u])return; Dfs(son[u],nw);
    	for(int i=lst[u];i;i=nxt[i])
    	if(to[i]^fa[u] && to[i]^son[u])Dfs(to[i],to[i]);
    }
    inline void Up(int rt) { sm[rt]=sm[rt<<1]+sm[rt<<1|1]; }
    void Build(int l,int r,int rt) {
    	if(l==r)return; register int mid=l+r>>1;
    	Build(l,mid,rt<<1),Build(mid+1,r,rt<<1|1);
    }
    inline void Down(int rt,int len) {
    	sm[rt<<1]=(len+1>>1)*tg[rt],tg[rt<<1]=tg[rt];
    	sm[rt<<1|1]=(len>>1)*tg[rt],tg[rt<<1|1]=tg[rt],tg[rt]=-1;
    }
    void Modify(int ql,int qr,int vl,int l,int r,int rt) {
    	if(ql<=l && r<=qr) { sm[rt]=vl*(r-l+1),tg[rt]=vl; return; }
    	register int mid=l+r>>1; if(tg[rt]!=-1)Down(rt,r-l+1);
    	if(ql<=mid)Modify(ql,qr,vl,l,mid,rt<<1);
    	if(qr>mid)Modify(ql,qr,vl,mid+1,r,rt<<1|1); Up(rt);
    }
    inline void Change(int x) {
    	for(;top[x]^top[1];x=fa[top[x]])
    		Modify(dfn[top[x]],dfn[x],1,1,n,1);
    	Modify(1,dfn[x],1,1,n,1);
    }
    int main() {
    	freopen("manager.in","r",stdin);
    	freopen("manager.out","w",stdout);
    	scanf("%d",&n);
    	for(int i=2,u;i<=n;i++) {
    		scanf("%d",&u),++u;
    		Ae(i,u),Ae(u,i);
    	}
    	Get(1,0),Dfs(1,1),Build(1,n,1);
    	scanf("%d",&T);
    	for(int u,pr,ft;T--;) {
    		scanf("%s%d",opt,&u),++u;
    		pr=sm[1];
    		if(opt[0]=='i')Change(u);
    		else if(opt[0]=='u')Modify(dfn[u],dfn[u]+sz[u]-1,0,1,n,1);
    		ft=sm[1];
    		printf("%d
    ",abs(pr-ft));
    	}
    }
    
  • 相关阅读:
    函数指针
    单链表的建立
    系统程序员成长计划组合的威力(三)
    通过XML构建TreeView
    关于Dll中导出string的问题
    关于类的拷贝构造函数、赋值构造函数探究
    系统程序员成长计划组合的威力(四)
    指纹识别软件安装包下载
    javaSE视频教程正式启动
    数组复习
  • 原文地址:https://www.cnblogs.com/KonjakLAF/p/14332248.html
Copyright © 2011-2022 走看看