【线段树】线段树系列 0.2单点修改区间求和线段树

1080 线段树练习

题目描述 Description

一行N个方格,开始每个格子里都有一个整数。现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和;修改的规则是指定某一个格子x,加上或者减去一个特定的值A。现在要求你能对每个提问作出正确的回答。1≤N<100000,,提问和修改的总数m<10000条。

输入描述 Input Description

输入文件第一行为一个整数N,接下来是n行n个整数,表示格子中原来的整数。接下一个正整数m,再接下来有m行,表示m个询问,第一个整数表示询问代号,询问代号1表示增加,后面的两个数x和A表示给位置X上的数值增加A,询问代号2表示区间求和,后面两个整数表示a和b,表示要求[a,b]之间的区间和。

输出描述 Output Description

共m行,每个整数

样例输入 Sample Input

6

4

5

6

2

1

3

4

1 3 5

2 1 4

1 1 9

2 2 6

样例输出 Sample Output

22

22

数据范围及提示 Data Size & Hint

1≤N≤100000, m≤10000 。

代码

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
struct node
{
    int left,right,value;
};
node point[1000000];
int father[1000000];
int g;

void buildtree(int i,int left,int right) //建树
{
    father[i]=(int)floor(i)/2.0;
    point[i].left=left;
    point[i].right=right;
    point[i].value=0;
    if (left==right) {father[i]=i;}
    else
    {
    buildtree(i<<1, left, (int)floor( (right+left) / 2.0));
    buildtree((i<<1) + 1, (int)floor( (right+left) / 2.0) + 1, right);
    }
}
//----------------------------------------------------------------------------
void update(int x,int add,int left,int right,int now) //更改
{
    int mid=(left+right)>>1;
    point[now].value+=add;
    if ( (right-left)<1 ) {g=left; return;}
    if ( (left<=x) && (x<=mid) ) { update(x,add,left,mid,2*now); }
    if ( ((mid+1)<=x) && (x<=right) ) { update(x,add,mid+1,right,2*now+1); }
}
//----------------------------------------------------------------------------
int search(int x,int left,int right,int begin,int end) //查找
{
    if ( (left==begin)&&(right==end) )  {return point[x].value;}
    int mid=(begin+end)>>1;
    int ans=0;

    if ( (left>=begin)&&(right<=mid) ) {ans+=search(2*x,left,right,begin,mid);}  //左边
    else if ( (left>=mid+1)&&(right<=end) ) {ans+=search(2*x+1,left,right,mid+1,end);}  //右边
    else {ans+=search(2*x,left,mid,begin,mid);
          ans+=search(2*x+1,mid+1,right,mid+1,end);}//中间
    return ans;
}
//----------------------------------------------------------------------------

int main()
{
    int n,m,k;
    cin>>n;
    buildtree(1,1,n);
    for (int i=1;i<=n;i++)
    {
        int ad;
        cin>>ad;
        update(i,ad,1,n,1);
    }
    cin>>m;
    for (int i=1;i<=m;i++)
    {
        int tmp;
        cin>>tmp;
        if (tmp==1)
        {
            int x,ad;
            cin>>x>>ad;
            update(x,ad,1,n,1);
        }
        if (tmp==2)
        {
            int p,q;
            cin>>p>>q;
            cout<<search(1,p,q,1,n)<<endl;
        }
    }
    return 0;
}
时间: 2024-08-06 00:24:16

【线段树】线段树系列 0.2单点修改区间求和线段树的相关文章

【线段树】线段树系列 0.1单点修改单点求和线段树

终于搞定了单点修改线段树...3个月..操蛋..根本没有模板题..觉得太弱了...艹蛋...必须进一步更新我的版本啊 #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; struct node { int left,right,value; }; node point[100]; int father[100]; int g; v

poj 2828 Buy Tickets 【线段树】【逆序插入 + 单点更新 + 区间求和】

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 16067   Accepted: 8017 Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get up early and join a long queue- The Lunar New Year wa

Lightoj 1348 Aladdin and the Return Journey (树链剖分)(线段树单点修改区间求和)

Finally the Great Magical Lamp was in Aladdin's hand. Now he wanted to return home. But he didn't want to take any help from the Genie because he thought that it might be another adventure for him. All he remembered was the paths he had taken to reac

树链剖分+线段树 单点修改 区间求和 模板

马上要去西安打邀请赛了,存下板子 首先是vector存图的: #include<bits/stdc++.h> using namespace std; #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define mid int m = (l + r) >> 1 const int M = 2e5+10; int fa[M],dep[M],siz[M],son[M

资瓷区间修改+区间求和的树状数组(一维/二维)

一维:令 \(v_i\) 为差分数组,那么 \([0, k]\) 的前缀和就是 \(\sum{v_i(k+1-i)} = (k+1) \cdot \sum{v_i} + \sum{v_i \cdot (-i)}\),树状数组维护一下 \(v_i\) 和 \(v_i \cdot i\) 即可. template <typename I> struct Fenwick { struct Node { I v0, v1; void add(I d0, I d1) { v0 += d0; v1 +=

hdu 1166 敌兵布阵(线段树之 单点更新+区间求和)

敌兵布阵                                                                             Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵

HYSBZ 1036 树链剖分(单点更新区间求和求最大值)

http://www.lydsy.com/JudgeOnline/problem.php?id=1036 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身 Input 输入

poj 1195 单点更新 区间求和

Mobile phones Time Limit: 5000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main [Submit] [Status] [Discuss] Description Suppose that the fourth generation mobile phone base stations in the Tampere area operate a

LightOJ 1112 Curious Robin Hood (单点更新+区间求和)

http://lightoj.com/volume_showproblem.php?problem=1112 题目大意: 1 i        将第i个数值输出,并将第i个值清0 2 i v     将第i个数值加v 3 i j      输出从i到j的数值和 简单的单点更新+区间求和,代码很简单的模板 但此题有一个神坑的地方当操作为1是输出第i个数值不是直接输出,而是通过查找输出(太坑了...) #include<stdio.h> #include<string.h> #incl