首页 > 其他分享 >超级树状数组

超级树状数组

时间:2025-01-01 19:10:51浏览次数:1  
标签:typedef ch 树状 int 超级 数组 include

超级树状数组,就是用树状数组来进行区间修改+区间查询操作的东西,好处是和线段树相比快了不少。

例题

首先先来复习一下普通的树状数组

int tree[MAXN];
int lowbit(int x) {
	return x & -x;
}
void update(int x, int d) {
	while (x <= n) {
		tree[x] += d;
		x += lowbit(x);
	}
}
int sum(int x) {
	int ans = 0;
	while (x) {
		ans += tree[x];
		x -= lowbit(x);
	}
	return ans;
}

注意: update 是 \(x\sim n\) 都加上 \(d\),sum 是求 \(1\sim x\)。


求区间 \(l\sim r\) 的问题,我们可以转化为求 \(1\sim k\) 的问题,对于这个问题,我们可以定义一个差分数组 \(d_i=a_i - a_{i - 1}\) 显然 \(a_i=d_1 + d_2 + ... + d_i\)。

\[\begin{aligned}&a_1+a_2+...+a_i\\=&~~d_1+(d_1+d_2)+(d_1+d_2+d_3)+...+(d_1+d_2+...+d_i)\\=&~~id_1+(i-1)d_2+...+[i-(i-1)]d_i\\=&~~i\sum\limits_{j=1}^i d_j-\sum\limits_{j=1}^i (j-1)d_j\end{aligned} \]

当求第一个数时,我们只需将 \(x\) 和 \(y+1\) 这两个差分数组更改,其他的差分数组要么没有被修改,要么被抵消掉了,当求第二个数时,我们也是将那两个数更改,其他的和前面的同理,对于这个数,自己推去吧。

#include <cstring>
#include <cstdio>
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#define endl '\n'
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef double db;
typedef pair<ll, ll> pll;

inline ll read() {
	char ch = getchar(); ll fu = 0, s = 0;
	while(!isdigit(ch)) fu |= (ch == '-'), ch = getchar();
	while(isdigit(ch)) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
	return fu ? -s : s;
}

const int MAXN = 1e5 + 10;
int n, m, a[MAXN];
struct Node {
	ll tree[MAXN];
	int lowbit(int x) {
		return x & -x;
	}
	void update(int x, ll d) {
		while (x <= n) {
			tree[x] += d;
			x += lowbit(x);
		}
	}
	ll sum(int x) {
		ll ans = 0;
		while (x) {
			ans += tree[x];
			x -= lowbit(x);
		}
		return ans;
	}
} tr1, tr2;

void solve() {
	n = read(), m = read();
	for (int i = 1; i <= n; i++) {
		a[i] = read();
		ll t = a[i] - a[i - 1];
		tr1.update(i, t);
		tr2.update(i, (i - 1) * t);
	}
	while (m--) {
		int op = read(), x = read(), y = read(), k;
		if (op == 1) {
			k = read();
			tr1.update(x, k);
			tr1.update(y + 1, -k);
			tr2.update(x, (x - 1) * k);
			tr2.update(y + 1, -y * k);
		} else {
			printf("%lld\n", (tr1.sum(y) * y - tr2.sum(y)) - (tr1.sum(x - 1) * (x - 1) - tr2.sum(x - 1)));
		}
	}
}

signed main() {
	int T = 1;
	// T = read();
	while(T--) solve();
	return 0;
}

标签:typedef,ch,树状,int,超级,数组,include
From: https://www.cnblogs.com/wh2011/p/18646187

相关文章

  • 2025-01-01:优质数对的总数Ⅰ。用go语言,给定两个整数数组 nums1 和 nums2,分别长度为 n
    2025-01-01:优质数对的总数Ⅰ。用go语言,给定两个整数数组nums1和nums2,分别长度为n和m,以及一个正整数k。如果nums1数组中的元素nums1[i]能被nums2数组中的元素nums2[j]乘以k除尽,则称(i,j)为一个优质数对(其中0<=i<=n-1,0<=j<=m-1)。请计算并返回所......
  • 字节多路通道、数组多路通道和选择通道
    在计算机系统中,通道(Channel)是一种用于连接输入输出设备(I/O设备)与内存之间的硬件组件,它负责数据的传输和控制。根据设计和功能的不同,通道可以分为多种类型,其中字节多路通道、数组多路通道和选择通道是三种常见的通道类型。1.字节多路通道(ByteMultiplexorChannel)特点:•字......
  • js数组-实例方法:Array.prototype.findLast(),Array.prototype.findLastIndex(),Array
    Array.prototype.findLast()findLast()方法反向迭代数组,并返回满足提供的测试函数的第一个元素的值。如果没有找到对应元素,则返回undefined语法findLast(callbackFn)findLast(callbackFn,thisArg)参数callbackFn:数组中测试元素的函数。回调应该返回一个真值,表示已......
  • 使用js写个方法对数组进行一分部翻转
    如果你想要创建一个JavaScript函数,该函数接受一个数组和一个索引作为参数,并在该索引处将数组分为两部分,然后交换这两部分的位置(即翻转),你可以按照以下方式实现:functionreverseAtIndex(arr,index){//验证输入是否有效if(!Array.isArray(arr)||index<0||index......
  • C语言一维数组与指针运算
    今天来着重讲解一下指针运算的方法遍历一维数组基本原理数组就是第一个数的地址,等价于一个指针,但是是开辟了空间的我就可以除了数组[]写法操作,也可以用指针指着操作,这里语法也十分重要,通过一道题咱们都领略一遍指针运算例题任务描述本关任务:编写程序,用指针实现以下功......
  • Day1算法刷题(数组板块)
    二分查找注意事项left<=right,等于不能漏掉,定位到同一个元素的时候也要判断和target是否相等left=mid+1,right=mid-1而不能是mid,否则会死循环,比如nums={1,2},target=2,此时mid就会一直指向1。补充:数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分......
  • Vue 对象 数组 添加/修改 数据
    注意:在vm(data)的根数据,不能使用Vm.set()/vm.$set()一、监视1、vue会监视data中所有层次的数据、2、对象数据a、对象中添加属性,vue默认不做响应b、对象添加属性,vue做响应,通过如下apiVue.set(target,属性,值)vue.$set(target,属性,值)3、数组数据a、使用apipush......
  • C语言数组名的理解
    一维数组intmain(){ inta[]={1,2,3,4}; printf("%zu\n",sizeof(a)); printf("%zu\n",sizeof(a+0)); printf("%zu\n",sizeof(*a)); printf("%zu\n",sizeof(a+1)); printf("%zu\n",sizeof(a[1])); prin......
  • 使用sort对以下数组进行排序
    在前端开发中,你可以使用JavaScript的Array.prototype.sort()方法对数组进行排序。以下是一个简单的例子:letarr=[5,2,8,9,1,4,6,3,7];arr.sort(function(a,b){returna-b;//升序排序//如果你想要降序排序,你可以返回b-a});console.log(arr)......
  • 使用js写一个方法生成从a-z的数组
    在JavaScript中,你可以使用以下方法生成一个包含从a到z的字母的数组:functiongenerateAlphabetArray(){constalphabet=[];for(letcharCode=97;charCode<=122;charCode++){alphabet.push(String.fromCharCode(charCode));}returnalphab......