zoukankan      html  css  js  c++  java
  • [BZOJ 4034] 树上操作

    Link:

    BZOJ 4034 传送门

    Solution:

    树剖模板题……

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    #define mid ((l+r)>>1)
    #define lc k<<1,l,mid
    #define rc k<<1|1,mid+1,r
    const int MAXN=1e5+10;
    struct edge{int to,nxt;}e[MAXN<<2];
    ll seg[MAXN<<2],tag[MAXN<<2];
    int n,m,x,y,head[MAXN],dep[MAXN],dat[MAXN],sz[MAXN],top[MAXN],pos[MAXN],f[MAXN],cnt,tot;
    
    void add_edge(int from,int to)
    {e[++tot].nxt=head[from];e[tot].to=to;head[from]=tot;}
    
    void dfs1(int x)
    {
        sz[x]=1;
        for(int i=head[x];i;i=e[i].nxt)
        {
            if(e[i].to==f[x]) continue;
            f[e[i].to]=x;dep[e[i].to]=dep[x]+1;
            dfs1(e[i].to);sz[x]+=sz[e[i].to]; 
        }
    }
    
    void dfs2(int x,int up)
    {
        int bs=0;top[x]=up;pos[x]=++cnt;
        for(int i=head[x];i;i=e[i].nxt)
            if(e[i].to!=f[x]&&sz[e[i].to]>sz[bs]) bs=e[i].to;
        if(!bs) return;
        dfs2(bs,up);
        for(int i=head[x];i;i=e[i].nxt)
            if(e[i].to!=f[x]&&e[i].to!=bs) dfs2(e[i].to,e[i].to);
    }
    
    void pushdown(int k,int l,int r)
    {
        if(!tag[k]) return;
        tag[k<<1]+=tag[k];tag[k<<1|1]+=tag[k];
        seg[k<<1]+=tag[k]*(mid-l+1);
        seg[k<<1|1]+=tag[k]*(r-mid);
        tag[k]=0;
    }
    
    void Update(int a,int b,int x,int k,int l,int r)
    {
        if(a<=l&&r<=b)
        {seg[k]+=1ll*x*(r-l+1);tag[k]+=x;return;}
        
        pushdown(k,l,r);
        if(a<=mid) Update(a,b,x,lc);
        if(b>mid) Update(a,b,x,rc);
        seg[k]=seg[k<<1]+seg[k<<1|1];
    }
    
    ll Query(int a,int b,int k,int l,int r)
    {
        if(a<=l&&r<=b) return seg[k];
        ll ret=0;pushdown(k,l,r);
        if(a<=mid) ret+=Query(a,b,lc);
        if(b>mid) ret+=Query(a,b,rc);
        return ret;
    }
    
    ll solve_query(int a,int b)
    {
        ll ret=0;
        while(top[a]!=top[b])
        {
            if(dep[top[a]]<dep[top[b]]) swap(a,b);
            ret+=Query(pos[top[a]],pos[a],1,1,n);
            a=f[top[a]];
        }
        if(pos[a]>pos[b]) swap(a,b);
        ret+=Query(pos[a],pos[b],1,1,n);
        return ret;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&dat[i]);
        for(int i=1;i<n;i++)
            scanf("%d%d",&x,&y),add_edge(x,y),add_edge(y,x);
        dfs1(1);dfs2(1,1);
        for(int i=1;i<=n;i++) Update(pos[i],pos[i],dat[i],1,1,n);
        
        while(m--)
        {
            int op,x,a;scanf("%d%d",&op,&x);
            if(op!=3) scanf("%d",&a);
            if(op==1) Update(pos[x],pos[x],a,1,1,n);
            else if(op==2) Update(pos[x],pos[x]+sz[x]-1,a,1,1,n); 
            else printf("%lld
    ",solve_query(1,x));
        }
        return 0;
    }
  • 相关阅读:
    Windows性能计数器应用
    Azure Oracle Linux VNC 配置
    Azure 配置管理系列 Oracle Linux (PART6)
    Azure 配置管理系列 Oracle Linux (PART5)
    Azure 配置管理系列 Oracle Linux (PART4)
    Azure 配置管理系列 Oracle Linux (PART3)
    Azure 配置管理系列 Oracle Linux (PART2)
    vagrant多节点配置
    docker基本操作
    LINUX开启允许对外访问的网络端口命令
  • 原文地址:https://www.cnblogs.com/newera/p/9297638.html
Copyright © 2011-2022 走看看