首页 > 其他分享 >loj144&145 dfs序+树状数组/线段树

loj144&145 dfs序+树状数组/线段树

时间:2023-11-22 09:25:21浏览次数:32  
标签:sz 145 int sum tr dfs add LL loj144

https://loj.ac/p/144
https://loj.ac/p/145

两题非常相似,一题的权值修改是在点上的,一题的权值修改是在整棵子树上的。

首先我们要了解dfs序,并记录每个节点的子树大小sz,对于一个节点,在dfs序上sz长的区间全都是他的子节点以及他自己。

所以我们将一棵树映射到了一个区间上,并且可以发现,两题分别是点修改+区间修改和区间修改+区间查询,考虑树状数组和线段树。

//loj144
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int mod = 998244353, INF = 1 << 30;
const int N = 1e6 + 10;
vector<int> e[N];
LL v[N], sz[N];
int dfn[N];
int n, m, r, cnt;
LL c[N]; //c数组是指每个下标管理的区间和


//点修 + 区间和
int lowbit(int x)
{
    return x & (-x);
}

void add(int p, LL k)
{
    for (; p <= n; p += lowbit(p)){
        c[p] += k;
    }
}

LL ask(int p) // 求[1, p]的前缀和
{
    LL s = 0;
    for (; p > 0; p -= lowbit(p)){
        s += c[p];
    }
    return s;
}


void dfs(int u, int fa)
{
    sz[u] = 1;
    dfn[u] = ++ cnt;
    for (int v: e[u]){
        if (v == fa) continue;
        dfs(v, u);
        sz[u] += sz[v];
    }
}


int main()
{
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cin >> n >> m >> r;
    for (int i = 1; i <= n; i ++){
        cin >> v[i];
    }

    for (int i = 1; i < n; i ++){
        int a, b;
        cin >> a >> b;
        e[a].push_back(b);
        e[b].push_back(a);
    }

    dfs(r, 0);
    for (int i = 1; i <= n; i ++){
        add(dfn[i], v[i]);
    }

    while (m --){
        int op; cin >> op;
        if (op == 1){
            int a;
            LL x;
            cin >> a >> x;
            add(dfn[a], x);
        }
        else if (op == 2){
            int a;
            cin >> a;
            LL ans = ask(dfn[a] + sz[a] - 1) - ask(dfn[a] - 1);
            cout << ans << endl;
        }
    }
    return 0;
}
//loj145
#include<bits/stdc++.h>
using namespace std;
#define lc p << 1
#define rc p << 1 | 1
typedef long long LL;
typedef pair<int, int> PII;
const int mod = 998244353, INF = 1 << 30;
const int N = 1e6 + 10;
int w[N];
int dfn[N], sz[N], v[N];
int n, m, r, cnt;
vector<int> e[N];
struct node{
	int l, r;
	LL sum, add;
}tr[N * 4];


// 区间修改 + 区间查询
void build(int p, int l, int r)
{
	tr[p] = {l, r, w[l], 0};
	if (l == r) return;
	int m = (l + r) >> 1;
	build(lc, l, m);
	build(rc, m + 1, r);	
	tr[p].sum = tr[lc].sum + tr[rc].sum;
}

void pushup(int p)
{
	tr[p].sum = tr[lc].sum + tr[rc].sum;
}

void pushdown(int p) // 懒节点下传
{
	if (tr[p].add){
		tr[lc].sum += tr[p].add * (tr[lc].r - tr[lc].l + 1);
		tr[rc].sum += tr[p].add * (tr[rc].r - tr[rc].l + 1);
		tr[lc].add += tr[p].add;
		tr[rc].add += tr[p].add;
		tr[p].add = 0;
	}
}

LL query(int p, int x, int y)
{
	if (x <= tr[p].l && tr[p].r <= y) return tr[p].sum;
	
	int m = (tr[p].l + tr[p].r) >> 1;
	pushdown(p);
	LL sum = 0;
	if (x <= m) sum += query(lc, x, y);
	if (y > m) sum += query(rc, x, y);
	return sum;	
}


void update(int p, int x, int y, LL k) //区间更新
{
	if (x <= tr[p].l && tr[p].r <= y){
		tr[p].sum += (tr[p].r - tr[p].l + 1) * k;
		tr[p].add += k;
		return;
	}
	int m = (tr[p].l + tr[p].r) >> 1;
	pushdown(p);
	if (x <= m) update(lc, x, y, k);
	if (y > m) update(rc, x, y, k);
	pushup(p);	
}


void dfs(int u, int fa)
{
    sz[u] = 1;
    dfn[u] = ++ cnt;
    for (int v: e[u]){
        if (v == fa) continue;
        dfs(v, u);
        sz[u] += sz[v];
    }
}


signed main()
{
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cin >> n >> m >> r;
    for (int i = 1; i <= n; i ++){
        cin >> v[i];
    }

    for (int i = 1; i < n; i ++){
        int a, b;
        cin >> a >> b;
        e[a].push_back(b);
        e[b].push_back(a);
    }
    dfs(r, 0);

    for (int i = 1; i <= n; i ++) w[dfn[i]] = v[i];
    build(1, 1, n);

    while (m --){
        int op; cin >> op;
        if (op == 1){
            int a;
            LL x;
            cin >> a >> x;
            update(1, dfn[a], dfn[a] + sz[a] - 1, x);
        }
        else if (op == 2){
            int a;
            cin >> a;
            LL ans = query(1, dfn[a], dfn[a] + sz[a] - 1);
            cout << ans << endl;
        }
    }
    return 0;
}

标签:sz,145,int,sum,tr,dfs,add,LL,loj144
From: https://www.cnblogs.com/lu1no/p/17848107.html

相关文章

  • HDFS与MAPREDUCE操作
     HDFS文件操作在分布式文件系统上验证HDFS文件命令,如下。hadoopfs[genericOpitions][-ls<path>] //显示目标路径当前目录下的所有文件[-lsr<path>] //递归显示目标路径下的所有目录及文件(深度优先)[-du<path>] //以字节为单位显示目录中所有文件的大小,或该文......
  • centos7.9 部署FastDFS+Nginx本地搭建文件服务器 高性能的文件服务器集群 同时实现在
    前言FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线......
  • DFS 序
      最近接触到一些DFS序的题,它可以用来解决一些关于子树的问题。  DFS序本质就是一棵树在深度优先搜索时访问节点的顺序。比如有下面一棵树,其DFS序就是$1\;2\;4\;7\;8\;5\;3\;6\;9$。  DFS序有一个很重要的性质,以节点$u$为根的子树中所有的节点......
  • 深度优先搜索(DFS)
    深度优先搜索(DFS)我们以二叉树的遍历为例子。先序遍历遍历过程访问根节点先序遍历其左子树先序遍历其右子树中序序遍历遍历过程中序遍历其左子树访问根节点中序遍历其右子树后序遍历遍历过程后序遍历其左子树后序遍历其右子树访问根节点我们使用数组来模拟......
  • HDFS
    目录HDFS1、HDFS概述1.1hdfs产生背景和意义1.2HDFS优缺点1.3HDFS组成架构1.4HDFS文件块大小2、HDFS的Shell(命令)3、API4、HDFS的读写流程(面试重点)4.1.1写入流程4.1.2网络拓扑-节点距离计算4.1.3机架感知4.2HDFS读数据流程5、NameNode和SecondaryNameNode5.1NN和2NN的......
  • DS145-16A-ASEMI整流二极管DS145-16A
    编辑:llDS145-16A-ASEMI整流二极管DS145-16A型号:DS145-16A品牌:ASEMI封装:TO-247特性:插件、整流二极管正向电流:45A反向耐压:1600V恢复时间:ns引脚数量:2芯片个数:1芯片尺寸:84MIL浪涌电流:150A漏电流:10ua工作温度:-55℃~150℃包装方式:500/盘;5000/箱备受欢迎的DS145-16A-ASEM......
  • dfs回溯算法,拨号
    题目电话号码的字母组合给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按任意顺序返回。给出数字到字母的映射如下(与电话按键相同)。注意1不对应任何字母。示例1:输入:digits="23"输出:["ad","ae","af","bd","be","bf","cd","ce",......
  • DFS和BFS
    DFS: acwing842递归搜索树 1#include<iostream>2usingnamespacestd;34constintN=10;5intn;6intpath[N];7boolst[N];89voiddfs(intu)10{11if(u==n)//一个分支走到头12{13for(inti=0;i<n;i++)......
  • CodeForces 1452E Two Editorials
    洛谷传送门CF传送门考虑枚举其中一个区间取\([i,i+K-1]\),考虑对于每个\(j\)一次性处理出,区间取\([j-K+1,j]\)多产生的贡献(即以\(j\)为右端点)。对于一个\([l_k,r_k]\),设其与\([i,i+K-1]\)的交长度为\(t\)。如果\(t=\min(r_k-l_k+1,K)\)则......
  • CF1450C1 Errich-Tac-Toe (Easy Version)
    思路如果去考虑O的摆放,再考虑那些改为X,这样不好思考,实现也很不好写,所以我们可以考虑构造一种通解。如果将上图所有标红的位置都放上X,那么无论O如何放,都不可能胜利,而X因为原本就没有,所以摆上后也不可能胜利。不过,因为更改的次数不能超过棋子总数的\(\frac13\),所以这......