zoukankan      html  css  js  c++  java
  • LOJ #145. DFS 序 2 题解

    CSDN同步

    原题链接

    板子题。

    考虑深搜,确定每个点的时间戳(即搜索顺序的编号吧)(operatorname{dfn}),然后记录 (operatorname{size}) 表示子树大小。为方便进一步叙述,(operatorname{Tree}) 表示子树集。

    时间戳的性质,其中有一: (forall v in operatorname{Tree}(u))(operatorname{dfn}(u) leq operatorname{dfn}(v) < operatorname{dfn}(u) + siz(u)). 即 (u) 子树内所有节点((v))的 (operatorname{dfn}) 是连续的。

    考虑到 (operatorname{dfn}) 连续,可以用线段树维护子树和变化。

    时间复杂度:(mathcal{O}(n + m log n)).

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=1e6+1;
    
    inline int read(){char ch=getchar(); int f=1; while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
    	int x=0; while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*f;}
    
    inline void write(int x) {
    	if(x<0) {putchar('-');write(-x);return;}
    	if(x<10) {putchar(char(x%10+'0'));return;}
    	write(x/10);putchar(char(x%10+'0'));
    }
    
    int n,m,root,v[N],cnt;
    int dfn[N],siz[N],val[N];
    vector<int> G[N];
    
    typedef long long ll;
    #define L (x<<1)
    #define R (x<<1)+1
    
    struct data {
    	int l,r; ll sum,tag;
    };
    data t[N<<2];
    
    struct BIT {
    	inline void update(int x) {
    		t[x].sum=t[L].sum+t[R].sum;	
    	}
    	inline void build_tree(int x,int l,int r) {
    		t[x].l=l; t[x].r=r; t[x].tag=0;
    		if(l==r) {t[x].sum=v[val[l]]; return;}
    		int mid=(l+r)>>1;
    		build_tree(L,l,mid); build_tree(R,mid+1,r);
    		update(x);
    	}
    	inline void pushdown(int x) {
    		ll p=t[x].tag; if(!p) return;
    		t[L].tag+=p; t[R].tag+=p;
    		t[L].sum+=p*(t[L].r-t[L].l+1);
    		t[R].sum+=p*(t[R].r-t[R].l+1);
    		t[x].tag=0;
    	}
    	inline void change(int x,int l,int r,int k) {
    		if(l<=t[x].l && t[x].r<=r) {t[x].tag+=k; t[x].sum+=1ll*k*(t[x].r-t[x].l+1);return;}
    		int mid=(t[x].l+t[x].r)>>1; pushdown(x);
    		if(l<=mid) change(L,l,r,k);
    		if(r>mid) change(R,l,r,k);
    		update(x);
    	}
    	inline ll ask(int x,int l,int r) {
    		if(l<=t[x].l && t[x].r<=r) return t[x].sum;
    		int mid=(t[x].l+t[x].r)>>1; ll ans=0; pushdown(x);
    		if(l<=mid) ans+=ask(L,l,r);
    		if(r>mid) ans+=ask(R,l,r);
    		return ans;
    	}
    } T;
    
    inline void dfs(int x,int fa) {
    	dfn[x]=++cnt; val[cnt]=x; siz[x]=1;
    	for(int i=0;i<G[x].size();i++) {
    		int y=G[x][i]; if(y==fa) continue;
    		dfs(y,x); siz[x]+=siz[y];
    	}
    }
    
    int main() {
    	n=read(),m=read(),root=read();
    	for(int i=1;i<=n;i++) v[i]=read();
    	for(int i=1;i<n;i++) {
    		int u=read(),v=read();
    		G[u].push_back(v);
    		G[v].push_back(u);
    	} dfs(root,0);
    	T.build_tree(1,1,n);
    	while(m--) {
    		int op=read(),a=read(),x;
    		if(op==1) {
    			x=read();
    			T.change(1,dfn[a],dfn[a]+siz[a]-1,x);
    		} else printf("%lld
    ",T.ask(1,dfn[a],dfn[a]+siz[a]-1));
    	}
    	return 0;
    }
    
    
    
    简易的代码胜过复杂的说教。
  • 相关阅读:
    Linux常用命令解释
    RAID 10 配置流程
    VMware workstation Windows 10虚拟机安装步骤
    yum仓库配置
    vi 常用命令
    Linux设备驱动动态插入内核与直接集成到内核方式的利弊分析
    常用的Linux命令行文本处理工具总结
    CentOS使用总结(不断更新)
    vsftpd出现“Response: 500 OOPS: cannot change directory”解决方法
    NFS共享服务挂载时出现“access denied by server while mounting”的解决方法
  • 原文地址:https://www.cnblogs.com/bifanwen/p/15072880.html
Copyright © 2011-2022 走看看