• BZOJ4034 T2


    Description

    有一棵点数为(N)的树,以点(1)为根,且树点有边权。然后有(M)个操作,分为三种:
    操作 1 :把某个节点(x)的点权增加(a)
    操作 2 :把某个节点(x)为根的子树中所有点的点权都增加(a)
    操作 3 :询问某个节点(x)到根的路径中所有点的点权和。

    Input

    第一行包含两个整数(N, M) 。表示点数和操作数。
    接下来一行(N)个整数,表示树中节点的初始权值。
    接下来(N-1)行每行三个正整数(fr, to), 表示该树中存在一条边((fr, to))
    再接下来(M)行,每行分别表示一次操作。其中第一个数表示该操作的种类$ 1-3 $ ,之后接这个操作的参数(x)或者(x,a)

    Output

    对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

    Sample Input

    5 5
    1 2 3 4 5
    1 2
    1 4
    2 3
    2 5
    3 3
    1 2 1
    3 5
    2 1 2
    3 3

    Sample Output

    6
    9
    13

    HINT

    对于(100\%)的数据,(N,M le 100000),且所有输入数据的绝对值都不会超过(10^{6})

    利用进栈出栈序列(dfs序),进栈权值为正,出栈为负,构建线段树。查询就是前缀和啦!!!

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    using namespace std;
    
    typedef long long ll;
    #define maxn (200010)
    ll n,m,L[maxn],R[maxn],side[maxn],next[maxn],toit[maxn],w[maxn],dfn[maxn],cnt,Ts,tag[maxn*4],zheng[maxn*4];
    ll sum[maxn*4];
    
    inline void add(ll a,ll b) { next[++cnt] = side[a]; side[a] = cnt; toit[cnt] = b; }
    inline void ins(ll a,ll b) { add(a,b); add(b,a); }
    
    inline void dfs(ll now,ll fa)
    {
    	dfn[++Ts] = now; L[now] = Ts;
    	for (ll i = side[now];i;i = next[i]) { if (toit[i] == fa) continue; dfs(toit[i],now); }
    	dfn[++Ts] = -now; R[now] = Ts;
    }
    
    inline void build(ll l,ll r,ll now)
    {
    	if (l == r) { zheng[now] = dfn[l] > 0; sum[now] = (dfn[l] > 0?1:-1)*w[abs(dfn[l])]; return; }
    	ll mid = (l + r)>>1;
    	build(l,mid,now<<1); build(mid+1,r,now<<1|1);
    	sum[now] = sum[now<<1]+sum[now<<1|1];
    	zheng[now] = zheng[now<<1]+zheng[now<<1|1];
    }
    
    inline void pushdown(ll now,ll l,ll r)
    {
    	if (!tag[now]) return;
    	if (l != r)
    	{
    		ll mid = (l+r)>>1;
    		sum[now<<1] += zheng[now<<1]*tag[now];
    		sum[now<<1|1] += zheng[now<<1|1]*tag[now];
    		sum[now<<1] -= (mid-l+1-zheng[now<<1])*tag[now];
    		sum[now<<1|1] -= (r-mid-zheng[now<<1|1])*tag[now];
    		tag[now<<1] += tag[now]; tag[now<<1|1] += tag[now];
    	}
    	tag[now] = 0;
    }
    
    inline void modify(ll ql,ll qr,ll key,ll l,ll r,ll now)
    {
    	pushdown(now,l,r);
    	if (ql <= l&&r <= qr)
    	{
    		sum[now] += zheng[now]*key;
    		sum[now] -= (r-l+1-zheng[now])*key;
    		tag[now] += key; return;
    	}
    	ll mid = (l + r) >> 1;
    	if (qr <= mid) modify(ql,qr,key,l,mid,now<<1);
    	else if (ql > mid) modify(ql,qr,key,mid+1,r,now<<1|1);
    	else modify(ql,mid,key,l,mid,now<<1),modify(mid+1,qr,key,mid+1,r,now<<1|1);
    	sum[now] = sum[now<<1]+sum[now<<1|1];
    }
    
    inline ll query(ll ql,ll qr,ll l,ll r,ll now)
    {
    	pushdown(now,l,r);
    	if (ql <= l&&r <= qr) return sum[now];
    	ll mid = (l + r) >> 1;
    	if (qr <= mid) return query(ql,qr,l,mid,now<<1);
    	else if (ql > mid) return query(ql,qr,mid+1,r,now<<1|1);
    	else return query(ql,mid,l,mid,now<<1)+query(mid+1,qr,mid+1,r,now<<1|1);
    }
    
    int main()
    {
    	freopen("4034.in","r",stdin);
    	freopen("4034.out","w",stdout);
    	scanf("%lld %lld",&n,&m);
    	for (ll i = 1;i <= n;++i) scanf("%lld",w+i);
    	for (ll i = 1,a,b;i < n;++i) scanf("%lld %lld",&a,&b),ins(a,b);
    	dfs(1,0); build(1,n<<1,1);
    	while (m--)
    	{
    		ll opt; scanf("%lld",&opt);
    		if (opt == 1)
    		{
    			ll x,a; scanf("%lld %lld",&x,&a);
    			modify(L[x],L[x],a,1,n<<1,1);
    			modify(R[x],R[x],a,1,n<<1,1);
    		}
    		else if (opt == 2)
    		{
    			ll x,a; scanf("%lld %lld",&x,&a);
    			modify(L[x],R[x],a,1,n<<1,1);
    		}
    		else
    		{
    			ll x; scanf("%lld",&x);
    			printf("%lld
    ",query(1,R[x]-1,1,n<<1,1));
    		}
    	}
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Android开发常见问题及解决方法
    Jquery chosen动态设置值实例介绍 select Ajax动态加载数据 设置chosen和获取他们选中的值
    Unity3d 基于物理渲染Physically-Based Rendering之实现
    Unity3d 基于物理渲染Physically-Based Rendering之specular BRDF
    Unity3d HDR和Bloom效果(高动态范围图像和泛光)
    unity3d 制造自己的水体water effect(一)
    unity3d shader之Roberts,Sobel,Canny 三种边缘检测方法
    Unity3d shader之卡通着色Toon Shading
    NVIDIA CG语言 函数之所有数学类函数(Mathematical Functions)
    Unity3d 使用DX11的曲面细分
  • 原文地址:https://www.cnblogs.com/mmlz/p/5866677.html
Copyright © 2020-2023  润新知