• BZOJ 4034 [HAOI2015]树上操作(欧拉序+线段树)


    题意:

    有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
    操作,分为三种:
    操作 1 :把某个节点 x 的点权增加 a 。
    操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
    操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
     
    思路:
    处理出这棵树的欧拉序,入栈时为这个点的正权,出栈时为这个点的负权
    对于操作1,对x入栈点加a,出栈点减a
    对于操作2,对x入栈点到x出栈点所有的点执行操作1
    对于操作3,即查询点1的入栈点到x入栈点的点权和
     
    在正常的区间加线段树中,有一个add,add对区间和sum[root]的贡献为(r-l+1)*add
    对这一题,我们记入栈点的flg为1,出栈点的为-1,那么在flg求和的情况下,add对区间和的贡献为flg[root]*add
    正常搞线段树即可
     
    代码:
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
    #include<functional>
        
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
    #define lowbit(x) ((x)&(-x)) 
    
    using namespace std;
    
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef long long LL;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    
    const db eps = 1e-6;
    const int mod = 998244353;
    const int maxn = 2e6+100;
    const int maxm = 2e6+100;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    
    int n, m;
    ll a[maxn];
    vector<int>v[maxn];
    int tot;
    int in[maxn],out[maxn];//树上i的出、入在rk位置
    ll rk[maxn];
    int vis[maxn];//in 1 , out 0
    void dfs(int x, int fa){
        ++tot;in[x]=tot;rk[tot]=a[x];vis[tot]=1;
        for(int i = 0; i < (int)v[x].size(); i++){
            int y = v[x][i];
            if(y!=fa)dfs(y,x);
        }
        ++tot;out[x]=tot;rk[tot]=-a[x];vis[tot]=0;
    }
    ll flg[maxn],lazy[maxn];
    ll sum[maxn];
    void build(int l, int r, int root){
        if(l==r){
            if(vis[l])flg[root]=1;
            else flg[root]=-1;
            sum[root]=rk[l];
            return;
        }
        int mid = (l+r)>>1;
        build(lson);
        build(rson);
        sum[root]=sum[lc]+sum[rc];
        flg[root]=flg[lc]+flg[rc];
    }
    void pushdown(int l, int r, int root){
        if(!lazy[root])return;
        lazy[lc]+=lazy[root];
        lazy[rc]+=lazy[root];
        sum[lc]+=lazy[root]*flg[lc];
        sum[rc]+=lazy[root]*flg[rc];
        lazy[root]=0;
        return;
    }
    void update(int x, int y, int val, int l, int r, int root){
        int mid = (l+r)>>1;
        if(x<=l&&r<=y){
            lazy[root]+=val;
            sum[root]+=val*flg[root];
            return;
        }
        pushdown(l, r, root);
        if(x<=mid)update(x,y,val,lson);
        if(y>mid)update(x,y,val,rson);
        sum[root]=sum[lc]+sum[rc];
        return;
    }
    ll query(int x, int y, int l, int r, int root){
        int mid = (l+r)>>1;
        if(x<=l&&r<=y)return sum[root];
        pushdown(l, r, root);
        ll ans = 0;
        if(x<=mid)ans+=query(x,y,lson);
        if(y>mid)ans+=query(x,y,rson);
        return ans;
    }
    
    int main() {
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= n; i++){
            scanf("%lld", &a[i]);
        }
        for(int i = 1; i <= n-1; i++){
            int x, y;
            scanf("%d %d" ,&x, &y);
            v[x].pb(y);
            v[y].pb(x);
        }
        dfs(1,-1);
        build(1,tot,1);
        while(m--){
            int op, x, y;
            scanf("%d", &op);
            if(op==1){
                scanf("%d %d" ,&x ,&y);
                update(in[x],in[x],y,1,tot,1);
                update(out[x],out[x],y,1,tot,1);
            }
            else if(op==2){
                scanf("%d %d", &x ,&y);
                update(in[x],out[x],y,1,tot,1);
            }
            else{
                scanf("%d", &x);
                printf("%lld
    ",query(1,in[x],1,tot,1));
            }
        }
        return 0;
    }
    /*
    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
     */
  • 相关阅读:
    《机器与人》(读至第一章)
    Solution Architect
    InfoQ Trends Report
    阿里云场景化阿里云企业数字化转型售前方法PSA
    AWS 6R
    .NET Core Ecosystem
    《如何阅读一本书》
    《数字化转型方法论:落地路径与数据中台》
    《亿级流量网站架构核心技术》
    .NET面试题整理
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/11154749.html
Copyright © 2020-2023  润新知