首页 > 其他分享 >dfs序线段树

dfs序线段树

时间:2023-08-18 11:12:42浏览次数:41  
标签:rs int 线段 tr mid dfs add ql

dfs序线段树

1.树上操作

思路

遍历一整棵树,记录一下节点 \(u\) 的所对应的子树的节点数 \(siz_u\) 以及 \(dfs\) 序 \(dfn_u\)

根据整棵树的 \(dfs\) 序,我们可以把树变成了一个序列

再维护线段树,\(\text{update(l,r,x)}\) 表示将 \([\text{l,r}]\) 上值加上 \(x\).

\(\text{query(l,r)}\) 表示 \(\text{l,r}\) 上的区间和

操作 \(1\) 执行 \(\text{update(}dfn_a,dfn_a+size_a-1,x)\)

操作 \(2\) 执行 \(\text{query}(dfn_a,dfn_a+siz_a-1,x)\)

#include <bits/stdc++.h>
#define ls p << 1
#define rs p << 1 | 1
using namespace std;
const int N = 4e6 + 10, M = N * 2;
typedef long long ll;
int e[M], ne[M], idx, h[N], w[N];
int n, m, r, x;
int dfn[N], cnt, vis[N];
int st[N], ed[N];
struct node
{
    ll s, add;
} tr[N];
void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void dfs(int u)
{
    vis[u] = 1;
    dfn[++cnt] = w[u];
    st[u] = cnt;
    for (int i = h[u]; ~i; i = ne[i])
    {
        int j = e[i];
        if (!vis[j])
            dfs(j);
    }
    ed[u] = cnt;
}

void build(int p, int l, int r)
{
    if (l == r)
    {
        tr[p].s = dfn[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(ls, l, mid);
    build(rs, mid + 1, r);
    tr[p].s = tr[ls].s + tr[rs].s;
}

void pushdown(int p, int l, int r)
{
    int mid = (l + r) >> 1;
    tr[ls].s += tr[p].add * (mid - l + 1);
    tr[ls].add += tr[p].add;
    tr[rs].s += tr[p].add * (r - (mid + 1) + 1);
    tr[rs].add += tr[p].add;
    tr[p].add = 0;
}

void update(int p, int l, int r, int ql, int qr, int x)
{
    if (ql <= l && r <= qr)
    {
        tr[p].s += (1ll) * (r - l + 1) * x;
        tr[p].add += x;
        return;
    }
    pushdown(p, l, r);
    int mid = (l + r) >> 1;
    if (ql <= mid)
        update(ls, l, mid, ql, qr, x);
    if (qr > mid)
        update(rs, mid + 1, r, ql, qr, x);
    tr[p].s = tr[ls].s + tr[rs].s;
}

ll query(int p, int l, int r, int ql, int qr)
{
    if (ql <= l && r <= qr)
        return tr[p].s;
    pushdown(p, l, r);
    int mid = (l + r) >> 1;
    ll ans = 0;
    if (ql <= mid)
        ans += query(ls, l, mid, ql, qr);
    if (qr > mid)
        ans += query(rs, mid + 1, r, ql, qr);
    return ans;
}

int main()
{
    memset(h, -1, sizeof(h));
    cin >> n >> m >> r;
    for (int i = 1; i <= n; i++)
        cin >> w[i];
    for (int i = 1; i < n; i++)
    {
        int a, b;
        cin >> a >> b;
        add(a, b), add(b, a);
    }
    vis[0] = 1;
    dfs(r);
    build(1, 1, n);
    for (int i = 1; i <= m; i++)
    {
        int k, a;
        cin >> k >> a;
        if (k == 1)
        {
            cin >> x;
            update(1, 1, n, st[a], ed[a], x);
        }
        else
            cout << query(1, 1, n, st[a], ed[a]) << '\n';
    }
    return 0;
}

标签:rs,int,线段,tr,mid,dfs,add,ql
From: https://www.cnblogs.com/ljfyyds/p/17639866.html

相关文章

  • #yyds干货盘点#FastDFS配置Nginx访问
    下载相关依赖软件包yum-yinstallwgetmakezlibzlib-develgcc-c++libtoolopensslopenssl-develwgethttp://nginx.org/download/nginx-1.10.2.tar.gztar-xzvfnginx-1.10.2.tar.gz安装Nginxcdnginx-1.10.2./configure--prefix=/data/apps/nginx-download\--p......
  • 杭电23多校第九场Capoo on tree(二分+树链剖分+可持久化线段树)
    2023HDU多校9__Capooontree(二分+树链剖分+可持久化线段树)题目链接Solution\(Hint1\)考虑如何进行对某一相同点权的所有点进行点权\(+1\)操作,如果我们建立权值线段树,那只需要将权值为\(x\)的点并入权值\(x+1\)即可,但是这样就算我们建立以节点编号为版本的可持久化线段树,也是......
  • 线段树&树状数组
    P4246首先注意到两个点应该怎么联通,有可能直接走进去对吧,也有可能是绕一圈走过去,我们考虑整个在求连通性的时候最重要的是哪些点,是左上角,左下角,右上角和右下角,所以我们考虑维护他们之间的连通性。然后连通性很好合并,所以我我们可以把这个东西搬上线段树维护一大段区间的四个角互......
  • 线段树
    线段树\(1.0\)线段树\(1.0\)可以实现对区间内的数加减,查询区间和的操作。例题【模板】线段树1原理定义l,r:分别表示节点表示的区间的左端点与右端点。sum:节点表示的区间\([l,r]\)内数组元素之和。add:lazy标记,表示这个节点以下的所有子节点中的叶子表示的数......
  • HDFS shell 常用命令
    创建多级目录(-p):hadoopfs-mkdir-p/test/a/b 展示目录:hadoopfs-ls/ 递归展示:hadoopfs-ls-R/ 从HDFS上下载文件到本地:hadoopfs-get/test/a/b/h.txthadoopfs-copyToLocal  /test/a/b/h.txt 从本地上传文件到HDFS:hadoopfs-copyFromLocalhello......
  • 线段树进阶-分裂合并
    前置知识动态开点权值线段树相信各位都会线段树合并我们考虑对于两棵权值线段树,由于动态开点的缘故,这两棵树都是不满的我们考虑能不能把这两棵树所保存的信息合并在一起我们考虑这么一件事就是说,由于树不满,我们可以暴力扫分为三种情况(设把\(b\)所在树并到\(a\)内,\(a\)......
  • POJ 2828(线段树 单点更新)
    BuyTicketsTimeLimit: 4000MS MemoryLimit: 65536KTotalSubmissions: 16466 Accepted: 8201DescriptionRailwayticketsweredifficulttobuyaroundtheLunarNewYearinChina,sowemustgetupearlyandjoinalongqueue…TheLunarNewYearwasap......
  • DFS
    #include<bits/stdc++.h>usingnamespacestd;inta[5][5]={{0,1,1,0,0},{1,0,1,1,1},{1,1,0,0,0},{0,1,0,0,1},{0,1,0,1,0}};intvis[1001]={0};voiddfs(intx){ vis[x]=1; for(inti=0;i<=4;i++){ if(a[x][i]==1&&vis[i]==0){ cout<<"V&quo......
  • ZOJ 3911 线段树(区间更新)
    PrimeQueryTimeLimit: 1Second     MemoryLimit: 196608KBYouaregivenasimpletask.Givenasequence A[i] with NHerearetheoperations:Avl,addthevalue v toelementwithindex l.(1<=V<=1000)Ralr,replacealltheelementsofse......
  • HDU 4893(线段树区间更新)
    Wow!SuchSequence!TimeLimit:10000/5000MS(Java/Others)    MemoryLimit:65536/65536K(Java/Others)TotalSubmission(s):3856    AcceptedSubmission(s):1085ProblemDescriptionRecently,Dogegotafunnybirthdaypresentfromhisnewf......