• 线段树 POJ


    地址 https://vjudge.ppsucxtt.cn/problem/POJ-3468

    You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. 
    One type of operation is to add some given number to each number in a given interval. 
    The other is to ask for the sum of numbers in a given interval.
    
    Input
    The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
    The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
    Each of the next Q lines represents an operation.
    "C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
    "Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
    
    Output
    You need to answer all Q commands in order. One answer in a line.
    
    Sample Input
    10 5
    1 2 3 4 5 6 7 8 9 10
    Q 4 4
    Q 1 10
    Q 2 4
    C 3 6 3
    Q 2 4
    Sample Output
    4
    55
    9
    15
    Hint
    The sums may exceed the range of 32-bit integers.
    

    解答 题目的大意是
    给出一个整数数列, A[1] ~~ A[N]
    有以下两个操作
    1 Q a b 查询数组A[]中 索引a到索引b所有的数的和
    2 C a b c 对数组A[]中 索引a到索引b的所有的数 全部加上一个数c
    对于每个操作1的查询 打印出结果 结果占一行

    对于线段树方案,这是一个区间更新 区间查询的方案。
    对于区间更新,不能高效的实现对一段区域添加一个值,因为需要对这个区间相关的所有节点均进行更新
    todo

    #define  _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include <vector>
    #include <assert.h>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 100010;
    
    struct Node {
    	int l; int r;
    	long long sum;
    	long long add;
    }t[4 * N];
    int arr[N];
    
    int n, m;
    
    void build(int p, int l, int r) {
    	t[p].l = l; t[p].r = r;
    	if (l == r) { t[p].sum = arr[l]; return; }
    
    	int mid = (l + r) >> 1;
    	build(p * 2, l, mid);
    	build(p * 2 + 1, mid + 1, r);
    	t[p].sum = t[p * 2].sum + t[p * 2 + 1].sum;
    }
    
    void pushDown(int p) {
    	if (t[p].add) {
    		t[p * 2].sum += t[p].add*(t[p*2].r-t[p*2].l+1);
    		t[p * 2+1].sum += t[p].add*(t[p * 2+1].r - t[p * 2+1].l + 1);
    		t[p * 2].add += t[p].add;
    		t[p * 2+1].add += t[p].add;
    		t[p].add = 0;
    	}
    }
    
    
    void update(int p, int l, int r, int d) {
    	if (l <= t[p].l && r >= t[p].r) {
    		t[p].sum += (long long)d* (t[p].r - t[p].l + 1);
    		t[p].add += d;
    		return;
    	}
    	pushDown(p);
    	int mid = (t[p].l + t[p].r) >> 1;
    	if (l <= mid) update(p * 2, l, r, d);
    	if (r > mid) update(p * 2 + 1, l, r, d);
    	t[p].sum = t[p * 2].sum + t[p * 2 + 1].sum;
    }
    
    
    long long query(int p, int l, int r) {
    	if (l <= t[p].l && r >= t[p].r) return t[p].sum;
    	pushDown(p);
    	int mid = (t[p].l + t[p].r) >> 1;
    	long long val = 0;
    	if (l <= mid) val += query(p * 2, l, r);
    	if (r > mid) val += query(p * 2 + 1, l, r);
    	return val;
    }
    
    int main()
    {
    	cin >> n >> m;
    	for (int i = 1; i <= n; i++) {
    		scanf("%d",&arr[i]);
    	}
    	
    	build(1, 1, n);
    
    	for (int i = 0; i < m; i++) {
    		char Q[2];
    		int j, k, l;
    		scanf("%s", &Q);
    
    		if (Q[0] == 'Q') {
    			scanf("%d%d",&j,&k);
    			printf("%lld
    ", query(1,j,k));
    		}
    		else if(Q[0]=='C') {
    			scanf("%d%d%d", &j, &k,&l);
    			update(1,j,k,l);
    		}
    		else {
    			assert(0);
    		}
    	}
    
    	return 0;
    }
    

    标记永久化模式

    // 111111111111.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
    //
    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 100010;
    
    struct SEGMENT_TREE {
    	int l; int r;
    	long long sum; long long tag;
    }tr[N*4];
    
    int n, q;
    int arr[N];
    
    void build(int p,int l,int r ) {
    	tr[p].l = l; tr[p].r = r;
    	if (l == r) {
    		tr[p].tag = 0;
    		tr[p].sum = arr[l];
    		return;
    	}
    
    	int mid = (l + r) >> 1;
    	build(p*2,l, mid);
    	build(p*2+1,mid + 1, r);
    	tr[p].sum = tr[p * 2].sum + tr[p*2+1].sum;
    }
    
    
    long long query(int p, int L, int R) {
    	int l = tr[p].l; int r = tr[p].r;
    
    	if (L <= l && r <= R)
    		return  tr[p].sum;
    
    	int mid = (l + r) >> 1;
    	long long tot = tr[p].tag *(min(r, R) - max(l, L) + 1);
    	if (L <= mid) tot += query(p * 2, L, R);
    	if (mid < R) tot += query(p * 2 + 1, L, R);
    
    	return tot;
    }
    
    void update(int L, int R, int d, int p) {
    	int l = tr[p].l; int r = tr[p].r;
    	if (L <= l && r <= R) {
    		tr[p].tag += d;
    		tr[p].sum += d * (r - l + 1);
    		return;
    	}
    
    	int mid = (l + r) >> 1;
    	if (L <= mid) update(L, R, d, p*2);
    	if (mid < R) update(L, R, d, p*2+1);
    	// pushup 操作需要将当前节点内的标记也算上
    	tr[p].sum = tr[p*2].sum + tr[p*2+1].sum + tr[p].tag * (r - l + 1);
    }
    
    
    
    
    int main()
    {
    	scanf("%d%d", &n, &q);
    
    	for (int i = 1; i <= n; i++) {
    		scanf("%d",&arr[i]);
    	}
    
    	build(1,1,n);
    
    	while (q--) {
    		char t[10];
    		int L, R, d;
    		scanf("%s%d%d", t, &L, &R);
    		if (t[0] == 'Q') {
    			printf("%lld
    ", query(1,L, R));
    		}
    		else {
    			scanf("%d", &d);
    			update(L, R, d, 1);
    		}
    	}
    	return 0;
    }
    
    

    我的视频题解空间

    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    BIOS中的UEFI和Legacy启动模式
    php和java中的加密和解密
    Linux 的进程状态
    C++继承:公有,私有,保护
    编译器在构造函数里都做了些什么?
    操作符重载
    C++对象模型学习笔记
    sizeof操作符-结构体与类大小
    C++之智能指针
    C/C++笔试题整理
  • 原文地址:https://www.cnblogs.com/itdef/p/15368558.html
Copyright © 2020-2023  润新知