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\n",T.ask(1,dfn[a],dfn[a]+siz[a]-1));
	}
	return 0;
}


posted @ 2021-07-28 22:14  bifanwen  阅读(111)  评论(3编辑  收藏  举报