0
点赞
收藏
分享

微信扫一扫

树状数组入门

乐百川 2022-02-03 阅读 53

树状数组是一种存储方式,比较方便的读写

//区间查询
int a[maxn], c[maxn];
int lowbit(int x)
{
	return x & (-x);
}
int getsum(int x)
{
	int sum = 0;
	for (; x; x -= lowbit(x))
		sum += c[x];
	return sum;
}
void add(int x)
{
	for (; x < maxn; x += lowbit(x))
		c[x]++;
}
int main()
{
	int n, i,x,y;
	cin >> n;
	for (i = 0; i < n; i++)
	{
		scanf("%d%d", &x, &y);
		x++;		//从1开始储存
		a[getsum(x)]++;
		add(x);
	}
	for (i = 0; i < n; i++)
	{
		printf("%d\n", a[i]);
	}
	return 0;
}
//树状数组+差分数组
ll b[maxn], c[maxn], n;
ll lowbit(ll x)
{
	return x & (-x);
}
void addone(ll x, ll y)
{
	ll z = x * y;
	for (; x <= n; x += lowbit(x))
	{
		c[x] += y;
		b[x] += z;
	}
}
void addall(ll l, ll r, ll y)
{
	addone(l, y);
	addone(r + 1, -y);
}
ll getsum(ll x)
{
	ll sum1 = 0, sum2 = 0;
	ll y = x + 1;
	for (; x; x -= lowbit(x))
	{
		sum1 += c[x];
		sum2 += b[x];
	}
	return sum1 * y - sum2;
}
ll query(ll l, ll r)
{
	return getsum(r) - getsum(l - 1);
}
int main()
{
	int nn, i, x, y, choice, l, r;
	cin >> n >> nn;
	for (i = 1, y = 0; i <= n; i++)
	{
		scanf("%d", &x);
		addone(i, x - y);
		y = x;
	}
	while (nn--)
	{
		scanf("%d", &choice);
		if (choice == 1)
		{
			scanf("%d%d%d", &l, &r, &x);
			addall(l, r, x);
		}
		else
		{
			scanf("%d%d", &l, &r);
			printf("%lld\n", query(l, r));
		}
	}
	return 0;
}
举报

相关推荐

0 条评论