树状数组

树状数组

佐手、 提交于 2019-12-04 02:36:48
题目 树状数组模板1 题目大意:给定一个序列,要求支持两种操作:1.将某个数加上 \(x\) ,2.查询区间某部分的和。 题目 树状数组模板2 题目大意:给定一个序列,要求支持两种操作:1.将区间内的每个数加上 \(x\) ,2.查询某个数。 分析 由于第一题与第二题实际上是等价的(稍后会说明),我们以下仅讨论第一题。我们先以最简单的数组来考虑,显然操作1是 \(O(1)\) ,操作2是 \(O(n)\) 的,总体复杂度 \(O(nm)\) ,很明显会超时。这时我们就会想到用前缀和来优化操作2,这样的话操作2是 \(O(1)\) 的,但是操作1是 \(O(n)\) 的,总体复杂度仍为 \(O(nm)\) ,会超时。有没有一种数据结构,可以使操作1和操作2都是 \(O(1)\) 的呢?仅目前来看是不存在的。于是我们退而求其次寻找一种数据结构,使操作1和操作2都是 \(O(\log n)\) 的。 树状数组(又称二叉索引树,Fenwick树)是一类最基础的树形数据结构。它支持 \(O(\log n)\) 进行区间修改单点查询或区间查询单点修改,亦即上述两道题的操作。具体来说,树状数组自身本质上仍是一个数组。我们令 \(a\) 为原数组, \(c\) 为树状数组,假定 \(i\) 二进制最后有 \(j\) 个0,则有 \(c_i=\sum_{k=0}^{2^j}a_{i-k}\) 。

P3368 【模板】树状数组 2

↘锁芯ラ 提交于 2019-12-04 00:22:40
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的值 输入格式 第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。 接下来M行每行包含2或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k 操作2: 格式:2 x 含义:输出第x个数的值 输出格式 输出包含若干行整数,即为所有操作2的结果。 输入输出样例 输入 #1 复制 5 5 1 5 4 2 3 1 2 4 2 2 3 1 1 5 -1 1 3 5 7 2 4 输出 #1 复制 6 10 说明/提示 时空限制:1000ms,128M 数据规模: 对于30%的数据:N<=8,M<=10 对于70%的数据:N<=10000,M<=10000 对于100%的数据:N<=500000,M<=500000 样例说明: 故输出结果为6、10 30分代码(暴力) #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<queue> using namespace std; int n,m,a,xx,yy,k

P3374 【模板】树状数组 1

这一生的挚爱 提交于 2019-12-04 00:21:51
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入格式 第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。 接下来M行每行包含3个整数,表示一个操作,具体如下: 操作1: 格式:1 x k 含义:将第x个数加上k 操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和 输出格式 输出包含若干行整数,即为所有操作2的结果。 输入输出样例 输入 #1 复制 5 5 1 5 4 2 3 1 1 3 2 2 5 1 3 -1 1 4 2 2 1 4 输出 #1 复制 14 16 说明/提示 时空限制:1000ms,128M 数据规模: 对于30%的数据:N<=8,M<=10 对于70%的数据:N<=10000,M<=10000 对于100%的数据:N<=500000,M<=500000 样例说明: 故输出结果14、16 #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<queue> using namespace std; int n,m,a,xx,yy; int c[500000]

线段树与树状数组

爷,独闯天下 提交于 2019-12-03 20:52:50
posted on 2019-10-06 22:08:50 【模板】线段树 1 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> using namespace std; typedef long long lld; int n ,m; const int N = 1e5 + 5; lld sum[N << 2], tag[N << 2]; void pushup(int u) { sum[u] = sum[u << 1] + sum[u << 1 | 1]; } void build(int u, int l, int r) { if(l == r) { cin >> sum[u]; return; } int mid = l + r >> 1; build(u << 1, l, mid); build(u << 1 | 1, mid + 1, r); pushup(u); } void update(int u, int l, int r, int x) { tag[u] += x; sum[u] += (lld)x * (r - l + 1); } void pushdown(int u, int l

树状数组

点点圈 提交于 2019-12-03 14:08:33
用于一些单点修改 和 区间的 查询 主要代码: 树底元素很关键,一般按着顺序排列吗》? int lowbit(int x) { return x&(-x); } void work(int x,int k) { for(ri i=x;i<=n;i+=lowbit(i)) tree[i]+=k; } int query(int x) { int ans=0; for(ri i=x;i>=1;i-=lowbit(i)) ans+=tree[i]; return ans; } 来源: https://www.cnblogs.com/Lamboofhome/p/11798376.html

树状数组题目合集

感情迁移 提交于 2019-12-03 10:12:16
单点更新 区间查询 敌兵布阵 坑点:cin cout 一直超时 改成 scanf 和printf 就过了 /*输入 t样例 N(N<=50000) 第i个正整数ai代表第i个工兵营地里开始时有ai个人(1<=ai<=50)。 接下来每行有一条命令,命令有4种形式: (1) Add i j,i和j为正整数,表示第i个营地增加j个人(j不超过30) (2)Sub i j ,i和j为正整数,表示第i个营地减少j个人(j不超过30); (3)Query i j ,i和j为正整数,i<=j,表示询问第i到第j个营地的总人数; (4)End 表示结束,这条命令在每组数据最后出现; 1 10 1 2 3 4 5 6 7 8 9 10 Query 1 3 Add 3 6 Query 2 7 Sub 10 2 Add 6 3 Query 3 10 End 输出 Case 1: 6 33 59 */ #include <string.h> #include <stdio.h> using namespace std; int n,t[50005]; int lowbit(int x) { return x&(-x); } void update(int x,int val)//单点更新 { while(x<=n){ t[x]+=val; x+=lowbit(x);//由叶子节点向上更新树状数组C

树状数组模板1

我是研究僧i 提交于 2019-12-03 07:21:44
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入格式 第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。 接下来M行每行包含3个整数,表示一个操作,具体如下: 操作1: 格式:1 x k 含义:将第x个数加上k 操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和 输出格式 输出包含若干行整数,即为所有操作2的结果。 输入输出样例 输入 #1 复制 5 5 1 5 4 2 3 1 1 3 2 2 5 1 3 -1 1 4 2 2 1 4 输出 #1 复制 14 16 说明/提示 时空限制:1000ms,128M 数据规模: 对于30%的数据:N<=8,M<=10 对于70%的数据:N<=10000,M<=10000 对于100%的数据:N<=500000,M<=500000 #include<bits/stdc++.h> typedef long long ll; using namespace std; const int maxn=2e7+9; const int MAX=1e5+9; int n; ll a[maxn]; inline int lowbit(int x) { return x&(-x); }

树状数组模板2

六眼飞鱼酱① 提交于 2019-12-03 07:21:41
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的值 输入格式 第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。 接下来M行每行包含2或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k 操作2: 格式:2 x 含义:输出第x个数的值 输出格式 输出包含若干行整数,即为所有操作2的结果。 输入输出样例 输入 #1 复制 5 5 1 5 4 2 3 1 2 4 2 2 3 1 1 5 -1 1 3 5 7 2 4 输出 #1 复制 6 10 说明/提示 时空限制:1000ms,128M 数据规模: 对于30%的数据:N<=8,M<=10 对于70%的数据:N<=10000,M<=10000 对于100%的数据:N<=500000,M<=500000 #include<bits/stdc++.h> typedef long long ll; using namespace std; const int maxn=2e7+9; const int MAX=1e5+9; int n; ll a[maxn]; inline int lowbit(int x) { return x&(-x); }

树状数组+欧拉降幂

◇◆丶佛笑我妖孽 提交于 2019-12-03 07:17:58
链接: https://ac.nowcoder.com/acm/problem/17190 来源:牛客网 题目描述 给一个长为n的序列,m次操作,每次操作: 1.区间 [l,r][l,r] [ l , r ]加 xx x 2.对于区间 [l,r][l,r] [ l , r ],查询 a[l]a[l+1]a[l+2]......a[l]^{a[l+1]^{a[l+2]......}} a [ l ] a [ l + 1 ] a [ l + 2 ] . . . . . . modmod m o d pp p,一直到 aa a- rr r 请注意每次的模数不同。 输入描述: 第一行两个整数 n,m 表示序列长度和操作数接下来一行,n个整数,表示这个序列接下来m行,可能是以下两种操作之一:操作1:区间[l,r]加上 x操作2:查询区间[l,r]的那个式子mod p的值 输出描述: 对于每个询问,输出一个数表示答案 示例1 输入 复制 6 4 1 2 3 4 5 6 2 1 2 10000007 2 2 3 5 1 1 4 1 2 2 4 10 输出 复制 1 3 1 备注: n , m <= 500000序列中每个数在 [1,2e9] 内,x <= 2e9 , p <= 2e7 #include<bits/stdc++.h> #include<tr1/unordered_map>

luogu_【模板】树状数组 2

风流意气都作罢 提交于 2019-12-03 07:13:18
树状数组记录修改,差分 #include<iostream> #include<cstdio> #define ri register int #define u int namespace opt { inline u in() { u x(0),f(1); char s(getchar()); while(s<'0'||s>'9') { if(s=='-') f=-1; s=getchar(); } while(s>='0'&&s<='9') { x=(x<<1)+(x<<3)+s-'0'; s=getchar(); } return x*f; } } using opt::in; #define NN 500005 namespace mainstay { u N,K; u c[NN],a[NN]; inline u ask(const u &x) { u _re(0); for(ri i(x); i; i-=i&-i) _re+=c[i]; return _re; } inline void add(const u &x,const u &y) { for(ri i(x); i<=N; i+=i&-i) c[i]+=y; } inline void solve() { N=in(),K=in(); for(ri i(1); i<=N; ++i) a[i]=in(); for