HYSBZ 4034 dfs序线段树

Posted chinesepikaync

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HYSBZ 4034 dfs序线段树相关的知识,希望对你有一定的参考价值。

题意反向翻译:

A tree with N points, with point 1 as the root, and the tree points have edge weights. Then there are M
There are three types of operations:
Operation 1: Increase a member‘s point weight by a.
Operation 2: Increase the point weights of all points in a subtree with x as the root by a.
Operation 3: Ask the sum of the weights of all points in the path from a shareholder x to the root.
The first line contains two integers N, M. Represents points and operands. The next line of N integers represents the initial weights of the nodes in the tree. Next N-1
Each row contains three positive integers fr, to, indicating that there is an edge (fr, to) in the tree. Then there are M lines, each of which represents an operation. among them
The first number indicates the kind of operation (1-3), followed by the parameter (x or xa) of this operation.
For each query operation, the answer to that query is output. Separate the answers with newlines.


欧拉序+线段树

              A
            /              B     C
         /                D     E     F

欧拉序就是进入到一个节点记一次,退出一个节点记一次

然后我们把进入到一个节点的那一次叫做+,退出的叫做-

ABDDEEBCFFCA
+++-+--++---

(u) 单点修改,因为对 (u) 加上一个 (val) 会对 (u) 的整个子树即 ([u_+,u_-)) 的答案产生影响,那么就在 (u_+) 加上 (val),在 (u_-) 减去 (val) 这样就不会影响到其他子树了

(u) 子树修改就相当于把整个 (u) 的子树进行单点修改,那么就把 ([u_+,u_-]) 中的所有 + 都加上 (val),所有 - 都减去 (val)

单点查询就直接查询 ([1,u_+]) 就行了

// This code writed by chtholly_micromaker(MicroMaker)
#include <bits/stdc++.h>
#define reg register
#define int long long
using namespace std;
const int MaxN=100050;
struct Edge
{
    int nxt,to;
}E[MaxN<<2];
template <class t> inline void read(t &s)
{
    s=0;
    reg int f=1;
    reg char c=getchar();
    while(!isdigit(c))
    {
        if(c=='-')
            f=-1;
        c=getchar();
    }
    while(isdigit(c))
        s=(s<<3)+(s<<1)+(c^48),c=getchar();
    s*=f;
    return;
}
int hd[MaxN],en,n,m;
int dfn[MaxN<<1],L[MaxN],R[MaxN],cnt;
int negative[MaxN<<1];
int cost[MaxN];
#define lson (u<<1)
#define rson (u<<1|1)
inline void adde(int u,int v)
{
    ++en;
    E[en]=(Edge){hd[u],v};
    hd[u]=en;
    return;
}
inline void dfs(int u,int fa)
{
    dfn[++cnt]=u;
    L[u]=cnt;
    negative[cnt]=0;
    for(int i=hd[u];~i;i=E[i].nxt)
    {
        reg int v=E[i].to;
        if(v==fa)
            continue;
        dfs(v,u);
    }
    dfn[++cnt]=u;
    R[u]=cnt;
    negative[cnt]=1;
    return;
}
int val[MaxN<<4],nega[MaxN<<4],lazy[MaxN<<4];
inline void pushup(int u)
{
    val[u]=val[lson]+val[rson];
    nega[u]=nega[lson]+nega[rson];
    return;
}
inline void pushdown(int u,int l,int r)
{
    if(lazy[u])
    {
        reg int mid=(l+r)>>1;
        lazy[lson]+=lazy[u];
        lazy[rson]+=lazy[u];
        val[lson]+=lazy[u]*(mid-l+1-2*nega[lson]);
        val[rson]+=lazy[u]*(r-mid-2*nega[rson]);
        lazy[u]=0;
    }
    return;
}
inline void buildtr(int u,int l,int r)
{
    if(l==r)
    {
        if(negative[l])
        {
            val[u]=-cost[dfn[l]];
            nega[u]=1;
        }
        else
        {
            val[u]=cost[dfn[l]];
            nega[u]=0;
        }
        return;
    }
    reg int mid=(l+r)>>1;
    buildtr(lson,l,mid);
    buildtr(rson,mid+1,r);
    pushup(u);
    return;
}
inline void change(int u,int l,int r,int p,int k)
{
    pushdown(u,l,r);
    if(l==r)
    {
        val[u]+=k;
        return;
    }
    reg int mid=(l+r)>>1;
    if(p<=mid)
        change(lson,l,mid,p,k);
    else
        change(rson,mid+1,r,p,k);
    pushup(u);
    return;
}
inline void modify(int u,int l,int r,int ql,int qr,int k)
{
    pushdown(u,l,r);
    if(ql<=l&&r<=qr)
    {
        val[u]+=k*(r-l+1-2*nega[u]);
        lazy[u]+=k;
        return;
    }
    reg int mid=(l+r)>>1;
    if(ql<=mid)
        modify(lson,l,mid,ql,qr,k);
    if(mid<qr)
        modify(rson,mid+1,r,ql,qr,k);
    pushup(u);
    return;
}
inline int query(int u,int l,int r,int ql,int qr)
{
    pushdown(u,l,r);
    if(ql<=l&&r<=qr)
        return val[u];
    reg int mid=(l+r)>>1,ans=0;
    if(ql<=mid)
        ans+=query(lson,l,mid,ql,qr);
    if(mid<qr)
        ans+=query(rson,mid+1,r,ql,qr);
    return ans;
}
inline void print()
{
    puts("=-=-=====-=-=-=-=");
    puts("segment");
    for(int i=1;i<=cnt;++i)
        printf("%lld ",query(1,1,cnt,i,i));
    puts("
=-=-==-=-=-=-=-=");
    return;
}
signed main(void)
{
    memset(hd,-1,sizeof hd);
    cin>>n>>m;
    reg int u,v;
    for(int i=1;i<=n;++i)
        read(cost[i]);
    for(int i=1;i<n;++i)
    {
        read(u);read(v);
        adde(u,v);
        adde(v,u);
    }
    dfs(1,0);
    buildtr(1,1,cnt);
    // print();
    reg int opt;
    for(int i=1;i<=m;++i)
    {
        read(opt);read(u);
        if(opt==1)
        {
            read(v);
            change(1,1,cnt,L[u],v);
            // printf("add %d 's val to %d
",L[u],v);
            change(1,1,cnt,R[u],-v);
            // printf("add %d 's val to %d
",R[u],-v);
        }
        else if(opt==2)
        {
            read(v);
            modify(1,1,cnt,L[u],R[u],v);
            // printf("modify [ %d , %d ] %d
",L[u],R[u],v);
        }
        else
            printf("%lld
",query(1,1,cnt,1,L[u]));
            // printf("Query [ %d ,  %d ] 
",1,L[u]);
    }
    return 0;
}

以上是关于HYSBZ 4034 dfs序线段树的主要内容,如果未能解决你的问题,请参考以下文章

DFS序+线段树(bzoj 4034)

bzoj 4034(DFS序+线段树)

BZOJ-4034: [HAOI2015]树上操作 (线段树+DFS序)

bzoj4034 树上操作 树链剖分+线段树

bzoj 4034

codevs1228 (dfs序+线段树)