码迷,mamicode.com
首页 > 编程语言 > 详细

【学习整理】树状数组 区间修改+查询

时间:2016-11-12 22:16:36      阅读:287      评论:0      收藏:0      [点我收藏+]

标签:latex   .com   names   stream   数列   ring   pos   print   需要   

前言:对于区间修改和区间查询这样的简单问题,打一大堆线段树确实是不划算,所以学习了区间修改+区间修查询的树状数组。

我们定义 技术分享 为原数列,技术分享 ,显然  技术分享

若想要将区间 技术分享 的数全部 技术分享 则只需要将 技术分享 , 技术分享 即可。

技术分享

              技术分享

              技术分享

所以,我们维护一个数组 技术分享 

将区间 技术分享 的数全部 技术分享 则还需同时将 技术分享 , 技术分享

结论:技术分享

 

例题:CODEVS1082 线段树练习3

http://codevs.cn/problem/1082/

 

 

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int n,q;
long long a[200005],c[3][200005];
long long lowbit(long long x){return x&(-x);}
void modify(int x,long long pos,long long v){for(;pos<=n;pos+=lowbit(pos)) c[x][pos]+=v;}
long long query(int x,long long pos){long long ret=0LL;for(;pos;pos-=lowbit(pos)) ret+=c[x][pos];return ret;}
int main()
{
    int i,j,opt;
    long long l,r,v,sum1,sum2;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        modify(1,i,a[i]-a[i-1]);
        modify(2,i,(i-1)*(a[i]-a[i-1]));
    }
    scanf("%d",&q);
    for(i=1;i<=q;i++)
    {
        scanf("%d%lld%lld",&opt,&l,&r);
        if(opt==1)
        {
            scanf("%lld",&v);
            modify(1,l,v);modify(1,r+1,-v);
            modify(2,l,v*(l-1));modify(2,r+1,-v*r); 
        } 
        else
        {
            sum1=(l-1)*query(1,l-1)-query(2,l-1);
            sum2=r*query(1,r)-query(2,r);
            printf("%lld\n",sum2-sum1);
        }
    }
    return 0;
    
}

【学习整理】树状数组 区间修改+查询

标签:latex   .com   names   stream   数列   ring   pos   print   需要   

原文地址:http://www.cnblogs.com/yljiang/p/6057394.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!