• 1082 线段树练习 3 && 树状数组区间修改区间查询


    1082 线段树练习 3

    题意: 给定序列初值, 要求支持区间修改, 区间查询

    Solution

    用树状数组, 代码量小, 空间占用小
    巧用增量数组, 修改时在 (l) 处 $ + val$ , (r + 1) 处 $ - val$, 在 (x) 处的值就是 (sum_{i = 1}^{x}c[i])
    这就是区间更新, 单点求值的树状数组

    那么怎么区间更新区间查询呢?
    设增量数组为 (b[i])
    显然, 查询 (1 - x) 的答案为: (sum_{i = 1}^{x}sum_{j = 1}^{i}b[i])
    这样还不明朗, 无法得到一个比较通项的前缀和, 所以进行如下变换:

    [sum_{i = 1}^{x}sum_{j = 1}^{i}b[i]$$$$=sum_{i = 1}^{x}(x - i + 1) * b[i]$$$$=(x + 1)sum_{i = 1}^{x}b[i] - sum_{i = 1}^{x}i * b[i] ]

    这样一来, 我们通过两个树状数组分别维护 (sum_{i = 1}^{x}b[i])(sum_{i = 1}^{x}i * b[i]), 即可快速计算得答案

    具体的, 第一个树状数组 我们在 (l) 处 $ + val$ , (r + 1)(- val), 第二个树状数组在 (l) 处 $ + l * val$, (r + 1)(- (r + 1) * val)
    (1-x)前缀和即为 ((x + 1) * get\_sum(x, 0) - get\_sum(x, 1))

    Code

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<climits>
    #define LL long long
    using namespace std;
    LL RD(){
        LL out = 0,flag = 1;char c = getchar();
        while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
        while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
        return flag * out;
        }
    const LL maxn = 400019;
    LL num, na;
    #define lowbit(i) ((i) & (-i))
    LL v[maxn], sum[maxn];
    LL c[maxn][2];
    void update(LL x, LL val, LL o){
    	for(LL i = x;i <= num;i += lowbit(i))c[i][o] += val;
    	}
    LL get_sum(LL x, LL o){
    	LL ans = 0;
    	for(LL i = x;i > 0;i -= lowbit(i))ans += c[i][o];
    	return ans;
    	}
    int main(){
    	num = RD();
    	for(LL i = 1;i <= num;i++)v[i] = RD(), sum[i] = sum[i - 1] + v[i];
    	na = RD();
    	for(LL i = 1;i <= na;i++){
    		LL cmd = RD(), l = RD(), r = RD();
    		if(cmd == 1){
    			LL val = RD();
    			update(l, val, 0), update(r + 1, -val, 0);
    			update(l, l * val, 1), update(r + 1, (r + 1) * -val, 1);
    			}
    		else{
    			printf("%lld
    ",sum[r] - sum[l - 1] + (r + 1) * get_sum(r, 0) - get_sum(r, 1) - l * get_sum(l - 1, 0) + get_sum(l - 1, 1));
    			}
    		}
    	}
    
  • 相关阅读:
    Vim快捷键,行首行尾
    java程序 cpu占用过高分析
    svn merge操作
    linux root用户无法删除文件,提示permission denied
    诡异问题:tomcat启动一直卡住,strace跟踪提示apache-tomcat核心文件找不到。
    转:xcode项目打不开:incompatible project version问题
    路由器当交换机用
    visual studio远程调试 remote debugger
    Sql server锁
    long 在不同操作系统下所占用的字节数
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9577828.html
Copyright © 2020-2023  润新知