【HDU 4027】线段树维护区间和

1.题目链接。题意简洁,就是两种操作,区间整体开方,区间求和。类似于区间修改操作但是我们没必要再加上懒惰标记,因为开方开多了这个点就会变成1,所以其实连续对区间操作,没有几次就不用进行修改了,我们特判一下区间都是1的情况,这样就直接修改不加懒惰标记也是可以的。

#include
#include
#include
#include
#define ll long long
#pragma warning(disable:4996)
using namespace std;
const int MAXN = 5000100;
ll a[MAXN];
struct Node
{
	int l, r;
     ll sum;
}seg[MAXN * 3];
void build(int i, int l, int r)
{
	seg[i].l = l;
	seg[i].r = r;
	if (l == r)
	{
		seg[i].sum= a[l];
		return;
	}
	int mid = ((l + r) >> 1);
	build(i << 1, l, mid);
	build((i << 1) | 1, mid + 1, r);
	seg[i].sum = seg[i << 1].sum + seg[(i << 1) | 1].sum;
}
void update(int i, int l, int r)
{
	if (seg[i].l == l && seg[i].r == r && seg[i].sum == r - l + 1) return;
	if (seg[i].l == seg[i].r)
	{
		seg[i].sum = sqrt(seg[i].sum*1.0);
		return;
	}
	int mid = ((seg[i].l + seg[i].r) >> 1);
	if (r <= mid) update(i << 1, l, r);
	else if (l > mid)  update((i << 1) | 1, l, r);
	else
	{
		update(i << 1, l, mid);
		update((i << 1) | 1, mid + 1, r);
	}
	seg[i].sum = seg[i << 1].sum + seg[(i << 1) | 1].sum;
}
long long SUM(int i, int l, int r)
{
	if (l == seg[i].l && r == seg[i].r) return seg[i].sum;

	int mid = ((seg[i].l + seg[i].r) / 2);
	long long ans = 0;

	if (r <= mid) ans = SUM(i << 1, l, r);
	else if (l > mid) ans = SUM((i << 1) | 1, l, r);
	else
	{
		ans += SUM(i << 1, l, mid);
		ans += SUM((i << 1) | 1, mid + 1, r);
	}
	return ans;
}
int main()
{
	
	int n;
	int T, X, Y;
	int iCase = 0;
	int M;
	while (scanf("%d", &n) != EOF)
	{
		iCase++;
		for (int i = 1; i <= n; i++)
			scanf("%lld", &a[i]);
		build(1, 1, n);
		scanf("%d", &M);
		printf("Case #%d:\n", iCase);
		while (M--)
		{
			scanf("%d%d%d", &T, &X, &Y);
			if (X > Y)swap(X, Y);
			if (T == 0) update(1, X, Y);
			else printf("%I64d\n", SUM(1, X, Y));
		}
		printf("\n");
	}
	return 0;
}

 

你可能感兴趣的:(数据结构与算法基于c++实现)