BZOJ4034 [HAOI2015] Operation on tree + DFS order + segment tree

Reference: https://www.cnblogs.com/liyinggang/p/5965981.html

Question meaning: It is a data structure question, on the tree, in the order of dfs, it becomes linear;

Idea: For each node x, record its DFS sequence, including the sequence number of the first arrival, record it with in[x], and record the sequence number out[x] of leaving,

Open another array seg, in: (serial number -> the value of the node); out: (serial number -> the negative value of the node);

This will make

  For trees: if the required interval completely contains an irrelevant subtree, this subtree does not affect the result;

  For a linear-based segment tree, both in[x] and out[x] intervals are included, and the sum of the intervals is 0;

Use the line segment tree to build the array seg to get the sum of the intervals;

so,

1-->Update the corresponding values ​​of in[x] and out[x] respectively;

2-->update in[x] to the value of out[x] interval;

3-->Return 1 (root) to in[x] interval;

#include <iostream>
#include <cstdio>
#include <vector>
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn = 200050;
ll sum[maxn*4];
ll seg[maxn],a[maxn],lazy[maxn*4],flag[maxn*4];
ll in[maxn],out[maxn];
ll io[maxn];
int cnt = 0;
int n,m;
vector <int> mp[maxn];
void dfs(int u,int fa)
{
    cnt++;
    seg[cnt] = 1ll*a[u],in[u] = 1ll*cnt;
    for(int i=0; i< mp[u].size(); i++)
    {
        int tmp  = mp[u][i];
        if(tmp == fa)continue;
        dfs(tmp,u);
    }
    cnt++;
    seg[cnt] = -1ll*a[u],out[u] = 1ll*cnt;  
    I [cnt] = - 1 ;
}
void pushup(int rt)
{
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    flag[rt] = flag[rt<<1] + flag[rt<<1|1];
}
void pushdown(int rt)
{
    if(lazy[rt])
    {
        lazy[rt<<1]  += lazy[rt]; 
        lazy[rt<<1|1]+= lazy[rt];
        sum[rt<<1]   += flag[rt<<1] * lazy[rt];    
        sum[rt<<1|1] += flag[rt<<1|1]*lazy[rt];
        lazy[rt] = 0;
    }
}
void build(int rt,int l,int r)
{
    if(l==r)
    {
        sum[rt] = seg[l];
        if(io[l]==0)flag[rt] = 1;
        else flag[rt] = -1;
        return ;
    }
    int mid = (l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}
    void update_one( int pos, int d, int l, int r, int rt) // Single point update; 
    {
         if (l == r)
        {
            if(flag[rt] ==1 )
                sum[rt] += d;
            else sum[rt] -= d;
            return;
        }
        pushdown(rt);
        int mid = (l+r)>>1;
        if(pos<=mid) update_one(pos,d,l,mid,rt<<1);
        else update_one(pos,d,mid+1,r,rt<<1|1);
        pushup(rt);
    }
    void update_d(int L,int R,int d,int l,int r,int rt)//区间更新;
    {
        if(l >= L && R >= r)
        {
            sum[rt] += flag[rt]*d;
            lazy[rt] += d;
            return;
        }
        pushdown(rt);
        int mid = (l+r)>>1;
        if(L<=mid) update_d(L,R,d,l,mid,rt<<1);
        if(R>mid) update_d(L,R,d,mid+1,r,rt<<1|1);
        pushup(rt);
    }
    ll query(int L,int R,int l,int r,int rt)//区间查询
    {
        if(l>=L&&r<=R)
        {
            return sum[rt];
        }
        int mid = (l+r)>>1;
        ll res = 0;
        pushdown(rt);
        if(mid>=L)res += query(L,R,l,mid,rt<<1);
        if(mid<R)res +=query(L,R,mid+1,r,rt<<1|1);
        return res;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n;i++)
        {
            scanf("%lld" ,&a[i]);
        }
        
        for(int i=1; i<n;i++)
        {
            int u, v;
            scanf("%d%d",&u,&v);
            mp[v].pb(u);
            mp[u].pb(v);
        }
        dfs(1,0);
        build(1,1,2*n);
        for(int i=1 ;i <= m; i++)
        {
            int op, x, val;
            scanf("%d", &op);
            if(op==1) { 
                scanf("%d%d",&x,&val);
                update_one(in[x],val,1,2*n,1);
                update_one(out[x],val,1,2*n,1);
            }
            else  if (op == 2 ) {
                scanf("%d%d",&x,&val);
                update_d(in[x],out[x],val,1,2*n,1);
            }
            else  if (op == 3 ) {    
                scanf("%d",&x);
                printf("%lld\n",query(1,in[x],1,2*n,1));
            }
        }
        return 0;
    }

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325021158&siteId=291194637