zoukankan      html  css  js  c++  java
  • 洛谷 P3372 【模板】线段树 1

    洛谷 P3372 【模板】线段树 1

    传送门

    思路

    前几天学了线段树的我,今天又去做了一遍线段树【模板】(1),发现自己打代码真的是漏洞百出啊,不过最后还是对了,所以来水一篇博客

    首先,这道模板题的要求就是:

    1.区间加
    2.区间求和

    这两个操作都属于线段树的基本操作

    前置——宏定义

    #define N 100011
    #define lson rt << 1
    #define rson rt << 1 | 1
    #define int long long
    

    由于我特别懒,不想写什么(rt << 1)之类的东西,所以直接宏定义就好了,还有,为了不改(int),我直接把(int)宏定义为(long long),省的麻烦(我真的是懒到家了)

    1.定义

    int sum[N << 2], lazy[N << 2], n, m;
    

    众所周知,线段树一般要开四倍空间,不明白的可以自己画一颗线段树数一下,sum数组维护区间和,lazy是懒标记

    2.pushup

    inline void pushup(int rt) {
    	sum[rt] = sum[lson] + sum[rson];
    }
    

    这是一个上传给父亲结点的信息的函数,当前节点的区间和就等于它左儿子和右儿子的区间和之和

    2.建树

    void build(int l, int r, int rt) {
    	if(l == r) {
    		sum[rt] = read();
    		return;
    	}
    	int m = (l + r) >> 1;
    	build(l, m, lson);
    	build(m + 1, r, rson);
    	pushup(rt);
    }
    

    上面是建树过程,(rt)表示当前节点,(lson)是左孩子,(rson) 是右孩子

    3.标记下放

    inline void pushdown(int l, int r, int rt) {
    	if(!lazy[rt]) return;
    	lazy[lson] += lazy[rt];
    	lazy[rson] += lazy[rt];
    	int m = (l + r) >> 1;
    	sum[lson] += (m - l + 1) * lazy[rt];
    	sum[rson] += (r - m) * lazy[rt];
    	lazy[rt] = 0;
    	return;
    }
    

    pushdown函数的实现:
    1.用lazy存储这个懒标记。
    2.递归到这个节点时,只更新这个节点的状态,并把当前的更改值累积到标记中。
    什么时候才用到这个懒标记?
    当需要递归这个节点的子节点时,标记下传给子节点。
    3.下放操作:(三步)
    当前节点的懒标记累积到子节点的懒标记中。
    修改子节点状态。
    父节点懒标记清0。

    4.区间修改

    void update(int L, int R, int c, int l, int r, int rt) {
    	if(L <= l && r <= R) {
    		sum[rt] += c * (r - l + 1);
    		lazy[rt] += c;
    		return;
    	}
    	pushdown(l, r, rt);
    	int m = (l + r) >> 1;
    	if(L <= m) update(L, R, c, l, m, lson);
    	if(R > m) update(L, R, c, m + 1, r, rson);
    	pushup(rt);
    }
    
    

    5.区间求和

    int query(int L, int R, int l, int r, int rt) {
    	if(L <= l && r <= R) return sum[rt];
    	pushdown(l, r, rt);
    	int m = (l + r) >> 1, ans = 0;
    	if(L <= m) ans += query(L, R, l, m, lson);
    	if(R > m) ans += query(L, R, m + 1, r, rson);
    	return ans;
    }
    

    代码

    下面上传高清无码无水印代码

    #include <bits/stdc++.h>
    #define N 100011
    #define lson rt << 1
    #define rson rt << 1 | 1
    #define int long long
    using namespace std;
    
    int sum[N << 2], lazy[N << 2], n, m;
    
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    	return x * f;
    }
    
    inline void pushup(int rt) {
    	sum[rt] = sum[lson] + sum[rson];
    }
    
    void build(int l, int r, int rt) {
    	if(l == r) {
    		sum[rt] = read();
    		return;
    	}
    	int m = (l + r) >> 1;
    	build(l, m, lson);
    	build(m + 1, r, rson);
    	pushup(rt);
    }
    
    inline void pushdown(int l, int r, int rt) {
    	if(!lazy[rt]) return;
    	lazy[lson] += lazy[rt];
    	lazy[rson] += lazy[rt];
    	int m = (l + r) >> 1;
    	sum[lson] += (m - l + 1) * lazy[rt];
    	sum[rson] += (r - m) * lazy[rt];
    	lazy[rt] = 0;
    	return;
    }
    
    void update(int L, int R, int c, int l, int r, int rt) {
    	if(L <= l && r <= R) {
    		sum[rt] += c * (r - l + 1);
    		lazy[rt] += c;
    		return;
    	}
    	pushdown(l, r, rt);
    	int m = (l + r) >> 1;
    	if(L <= m) update(L, R, c, l, m, lson);
    	if(R > m) update(L, R, c, m + 1, r, rson);
    	pushup(rt);
    }
    
    int query(int L, int R, int l, int r, int rt) {
    	if(L <= l && r <= R) return sum[rt];
    	pushdown(l, r, rt);
    	int m = (l + r) >> 1, ans = 0;
    	if(L <= m) ans += query(L, R, l, m, lson);
    	if(R > m) ans += query(L, R, m + 1, r, rson);
    	return ans;
    }
    
    signed main() {
    	n = read(), m = read();
    	build(1, n, 1);
    	for(int i = 1; i <= m; i++) {
    		int opt = read(), x = read(), y = read();
    		if(opt == 1) {
    			int k = read();
    			update(x, y, k, 1, n, 1);
    		}
    		if(opt == 2) cout << query(x, y, 1, n, 1) << '
    ';
    	}
    	return 0;
    }
    
  • 相关阅读:
    PostGIS安装教程
    报错:尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。
    flexpaper跨服务器访问swf不显示问题
    JSAPI 基于arcgis_js_api3.3的部署
    C# datatable排序(转)
    C# 未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”
    C# 正则表达式
    AE10.0在Visual Studio 2012下安装没有模板(转)
    AE安装部署以及监测ArcEngine runtime 9.3是否安装
    Flex带CheckBox的Tree(修改ItemRenderer)
  • 原文地址:https://www.cnblogs.com/loceaner/p/11122049.html
Copyright © 2011-2022 走看看