2020年9月12日普及组 T4 树【树状数组】【dfs序】

在这里插入图片描述
n n n 个点按照深度的奇偶性分类,
如果 i i i 的深度为奇数,我们令 f l a g [ i ] = 1 flag[i]=1 flag[i]=1
如果 i i i 的深度为偶数,我们令 f l a g [ i ] = − 1 flag[i]=-1 flag[i]=1
对于修改操作
我们给以 x x x 为根的那整棵子树的每个点加上 v a l ∗ f l a g [ x ] val*flag[x] valflag[x]
这可以用DFS序+树状数组 O ( l o g n ) O(logn) O(logn) 的时间复杂度内解决。
对于询问操作
我们在树状数组中算出 x x x 的权值 v a l val val,然后 x x x 的实际权值为 a [ x ] + v a l ∗ f l a g [ x ] a[x]+val*flag[x] a[x]+valflag[x]

代码

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int a[100010],v[100010],hd[100010],l[100010],r[1000010],flag[1000010],tree[1000010];
int n,m,x,y,c,val,tot,dep;

struct node
{
    
    
	int x,to,next;
}map[1000010];
void ljb(int x,int y)
{
    
    
	map[++tot].x=x;
    map[tot].to=y;
	map[tot].next=hd[x];
	hd[x]=tot;
}
int lowbit(int x)
{
    
    
	return x&-x;
}
void sum(int x,int w)   //修改
{
    
    
	while(x<=n)
	 {
    
    
	 	tree[x]+=w;
	 	x+=lowbit(x);
	 }
}
int findd(int x)     //查询
{
    
    
	int ans=0;
	while(x>=1)
	 {
    
    
	 	ans+=tree[x];
	 	x-=lowbit(x);
	 }
	return ans;
}
void dfsdep(int x,int fa)   //求DFS序
{
    
    
	dep++;  //深度不断++
	l[x]=dep;  //自己的深度
	flag[x]=-flag[fa];   //变换flag
	for(int i=hd[x]; i; i=map[i].next)
	 {
    
    
	 	if(map[i].to==fa)
	 	  continue;
	 	dfsdep(map[i].to,x);
	 }
	r[x]=dep;   //自己的子树的最大深度位置
}
int main()
{
    
    
	cin>>n>>m;
	for(int i=1; i<=n; i++)
	   cin>>a[i];
	for(int i=1; i<=n-1; i++)
	 {
    
    
	 	cin>>x>>y;
		ljb(x,y);
	 }
	flag[0]=-1;     //让第一个等于 1
	dfsdep(1,0);
	for(int i=1; i<=m; i++)
     {
    
    
     	cin>>c;
     	if(c==1)
     	 {
    
    
     	   cin>>x>>val;
     	   sum(l[x],val*flag[x]);  //往后差分
     	   sum(r[x]+1,-val*flag[x]);
		 }
		if(c==2)
		 {
    
    
		 	cin>>x;
		 	cout<<a[x]+findd(l[x])*flag[x]<<endl;
		 }
	 }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Jackma_mayichao/article/details/108551773
今日推荐