[模板]洛谷T3368 树状数组 模板2

1.对于区间修改:

直接修改数组c[],即进行n次add,肯定会TLE;

于是在此引入一个新数组:addv[],addv[i]指的是以结点i为根的树的所有元素加上addv[i]。

设将区间[a,b]中每个数加上x,

则只需自b向左,将相应的addv[]加上x,再自a-1向左,将多修改的结点的addv[]减去x即可。

2.对于单点查询:

设查询结点i,则其原值为:

(以结点i为根的树的所有元素的和)-(此树中除结点i之外的所有节点的和);

然后从结点i向树根遍历,将遍历到的节点的addv[]值加给之前已计算出的结点i的原值,最终结果就是结点i现在的值。

代码如下:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<ctime>
 5 #include<cstdlib>
 6 #include<algorithm>
 7 #include<string>
 8 #include<stack>
 9 #include<queue>
10 #include<vector>
11 using namespace std;
12 void add(int,int);
13 void update(int,int,int);
14 int query(int);
15 int c[500010];
16 int addv[500010];
17 int n,m;
18 int i,t;
19 int f;
20 int x,y,k;
21 int main(){
22     scanf("%d%d",&n,&m);
23     for(i=1;i<=n;i++){
24         scanf("%d",&t);
25         add(i,t);
26     }
27     for(i=1;i<=m;i++){
28         scanf("%d",&f);
29         if(f==1){
30             scanf("%d%d%d",&x,&y,&k);
31             update(x,y,k);
32         }
33         else{
34             scanf("%d",&x);
35             printf("%d\n",query(x));
36         }
37     }
38     return 0;
39 }
40 void add(int p,int x){
41     while(p<=n){
42         c[p]+=x;
43         p+=p&-p;
44     }
45 }
46 void update(int a,int b,int x){
47     while(b>=a){     //区间加
48         addv[b]+=x;
49         b-=b&-b;
50     }
51     a--;
52     while(a>b){     //区间减
53         addv[a]-=x;
54         a-=a&-a;
55     }
56 }
57 int query(int p){
58     int p1=p-(p&-p);
59     int p2=p-1;
60     int t=c[p];
61     while(p2>p1){
62         t-=c[p2];
63         p2-=p2&-p2;
64     }         //计算结点原值
65     while(p<=n){
66         t+=addv[p];
67         p+=p&-p;
68     }     //追加addv[]
69     return t;
70 }
时间: 2024-08-27 05:53:19

[模板]洛谷T3368 树状数组 模板2的相关文章

[模板]洛谷T3374 树状数组 模板1

1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<ctime> 6 #include<cstdlib> 7 8 #include<algorithm> 9 #include<string> 10 #include<stack> 11 #include<queue>

hdu 3584 二进制0,1反转 三维树状数组 及三维树状数组模板

先贴自己类比二维树状数组写的三维树状数组模板: 开始的时候循环体内j=y,k=z,没写,以为自己思路错了,,,hehe..... 更高维的树状数组以此类比 const int MAXN = 100+10; int c[MAXN][MAXN][MAXN];int X,Y,Z; int N; inline int lowbit(int x){return x&(-x);} void update(int x, int y, int z, int v) { int i=x,j=y,k=z; while

poj 1195 二维树状数组 及二维树状数组模板

http://poj.org/problem?id=1195 求矩阵和的时候,下标弄错WA了一次... 求矩形(x1,y1) (x2,y2)的sum |sum=sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1) 二维树状数组讲解:http://blog.csdn.net/u011026968/article/details/38532117 二维树状数组模板: /*========================================

二维树状数组模板(区间修改+区间查询)

二维树状数组模板(区间修改+区间查询) 例题:JOIOI上帝造题的七分钟 一共两种操作: \(L\ x_1\ y_1\ x_2\ y_2\ d\):把\((x_1,y_1)\),\((x_2,y_2)\)这个矩形内所有元素加\(d\). \(k\ x_1\ y_1\ x_2\ y_2\):查询\((x_1,y_1)\),\((x_2,y_2)\)这个矩形内所有元素的和. 代码如下: #include<bits/stdc++.h> #define RG register #define IL i

树状数组模板

看了很多讲解仍然不明就里,感觉反正代码很短,暂时当模板背过好了. //树状数组 单点修改 区间查询 const int maxn=1005; int tree[maxn],n; void init() { for (int i=1;i<=n;i++) tree[i]=0; } //初始化一个长度为n的树状数组,n为全局变量 int lowbit(it k) { return k&-k; } void add(int k,int x) //给位置k加x { while (k<=n) {

树状数组模板(改点求段 / 该段求点 / 改段求段)

1. 改点求段(单点更新, 区间求和) 代码: 1 #include <iostream> 2 using namespace std; 3 4 const int MAXN = 1e5 + 10; 5 int tree[MAXN], n; 6 7 int lowbit(int x){//返回 pow(2, k),其中k为末尾0的个数, 即返回最低位1的值 8 return x & -x; 9 } 10 11 void add(int x, int d){//将d累加到tree数组对应

树状数组模板 Tree Array

---恢复内容开始--- 这几天去浙江省选当垫底(Orz我是蒟蒻),然后顺便复习下树状数组 关于树状数组,其实很好理解,主要就是lowbit()操作的巧妙 树状数组是一种非常优雅的数据结构.当要频繁的对数组元素进行修改,同时又要频繁的查询数组内任一区间元素之和的时候,可以考虑使用树状数组. 换句话说,树状数组最基本的应用: 对于一个数组,如果有多次操作,每次的操作有两种:1.修改数组中某一元素的值,2.求和,求数组元素a[1]+a[2]+…a[num]的和. ——Km的小天地 其实树状数组自己写

OI模板(2) —— 树状数组(BIT)

在codevs上有模板题目,虽说是线段树模板,不过就题目描述来说,树状数组轻松水过 传送门:http://codevs.cn/problem/1080/ 能用线段树就不要用平衡树,能用树状数组就不要用线段树,这话是显然的,代码长度.难道上都有较大区别,BIT是最简单的一个 1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdlib> 5 #incl

树状数组模板1——单点修改区间查询

树状数组的模板,修改单点的值,查询某个区间 1 #include<cstdio> 2 #include<cctype> 3 using namespace std; 4 5 int c[500010],n,m; 6 7 int read() 8 { 9 int x=0,f=1; 10 char c=getchar(); 11 while (!isdigit(c)) 12 f=c=='-'?-1:1,c=getchar(); 13 while (isdigit(c)) 14 x=(x