zoukankan      html  css  js  c++  java
  • BZOJ 4034 线段树+DFS序

    思路:
    先搞出来每个点的DFS序 (要有入栈和出栈两种状态的)
    处理出来 线段树区间有多少入栈的和多少出栈的

    加区间的时候就加(入-出)*wei

    查前缀和

    //By SiriusRen
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 200050
    #define int long long
    int n,m,Wei[N],v[N],first[N],next[N],tot,start[N],end[N],cnt;
    int xx,yy,ww,op,tree[N*20],mark[N*20],marka[N*20],vv[N];
    void add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
    void dfs(int x,int fa){
        start[x]=++cnt;vv[cnt]=1;
        for(int i=first[x];~i;i=next[i])
            if(v[i]!=fa)
                dfs(v[i],x);
        end[x]=++cnt;vv[cnt]=-1;
    }
    void push_down(int pos){
        int lson=pos<<1,rson=pos<<1|1;
        tree[lson]+=mark[lson]*marka[pos];
        tree[rson]+=mark[rson]*marka[pos];
        marka[lson]+=marka[pos];
        marka[rson]+=marka[pos];
        marka[pos]=0;
    }
    void build(int l,int r,int pos){
        if(l==r){mark[pos]=vv[l];return;}
        int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
        build(l,mid,lson),build(mid+1,r,rson);
        mark[pos]=mark[lson]+mark[rson];
    }
    void insert(int l,int r,int pos,int wei,int x){
        if(l==r){tree[pos]+=wei;return;}
        if(marka[pos])push_down(pos);
        int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
        if(mid<x)insert(mid+1,r,rson,wei,x);
        else insert(l,mid,lson,wei,x);
        tree[pos]=tree[lson]+tree[rson];
    }
    int query(int l,int r,int pos,int x){
        if(r<=x){return tree[pos];}
        if(marka[pos])push_down(pos);
        int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
        if(mid>=x)return query(l,mid,lson,x);
        else return query(l,mid,lson,x)+query(mid+1,r,rson,x);
    }
    void Change(int l,int r,int pos){
        if(l>=xx&&r<=yy){
            marka[pos]+=ww;
            tree[pos]+=ww*mark[pos];
            return;
        }
        if(marka[pos])push_down(pos);
        int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
        if(mid<xx)Change(mid+1,r,rson);
        else if(mid>=yy)Change(l,mid,lson);
        else Change(l,mid,lson),Change(mid+1,r,rson);
        tree[pos]=tree[lson]+tree[rson];
    }
    signed main(){
        memset(first,-1,sizeof(first));
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++)scanf("%lld",&Wei[i]);
        for(int i=1;i<n;i++)
            scanf("%lld%lld",&xx,&yy),add(xx,yy),add(yy,xx);
        dfs(1,-1);
        build(1,cnt,1);
        for(int i=1;i<=n;i++)
            insert(1,cnt,1,Wei[i],start[i]),insert(1,cnt,1,-Wei[i],end[i]);
        for(int i=1;i<=m;i++){
            scanf("%lld",&op);
            if(op==1){
                scanf("%lld%lld",&xx,&ww);
                insert(1,cnt,1,ww,start[xx]);
                insert(1,cnt,1,-ww,end[xx]);
            }
            else if(op==2){
                scanf("%lld%lld",&xx,&ww);
                yy=end[xx],xx=start[xx];
                Change(1,cnt,1);
            }
            else if(op==3){
                scanf("%lld",&xx);
                printf("%lld
    ",query(1,cnt,1,start[xx]));
            }
        }
    }

    这里写图片描述

  • 相关阅读:
    不停机还能替换代码?6年的 Java程序员表示不可思议
    redis 分布式锁的 5个坑,真是又大又深
    一口气说出 4种 LBS “附近的人” 实现方式,面试官笑了
    真没想到,Springboot能这样做全局日期格式化,有点香!
    springboot + aop + Lua分布式限流的最佳实践
    不可思议的hexo,五分钟教你免费搭一个高逼格技术博客
    Redis开发运维的陷阱及避坑指南
    Jar包一键重启的Shell脚本及新服务器部署的一些经验
    与Redis的初次相识,Redis安装、启动与配置
    SpringBoot项目中应用Jedis和一些常见配置
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532162.html
Copyright © 2011-2022 走看看