【codevs 1082】线段树练习3

#include <cstdio>
#include <iostream>
#include <cstring>
#define ll long long
using namespace std;
int a[200000],n,Q;
struct edge{
	int l,r,add;ll sum; 
}node[200000*4];
void pushdown(int k)
{
	node[k<<1].add += node[k].add;
	node[k<<1].sum += (node[k<<1].r-node[k<<1].l+1)*node[k].add;
	node[(k<<1)+1].add += node[k].add;
	node[(k<<1)+1].sum += (node[(k<<1)+1].r-node[(k<<1)+1].l+1)*node[k].add;
	node[k].add = 0;
}

void update(int k,int left,int right,int x)
{
	if(left <= node[k].l && right >= node[k].r)
	{
		node[k].add += x;
		node[k].sum += (node[k].r-node[k].l+1)*x;
		return;
	}
	node[k].sum += (right-left+1)*x;
	if(node[k].add)pushdown(k);
	int mid = (node[k].l+node[k].r)>>1;
	if(right <= mid)update(k<<1,left,right,x);
	else if(left > mid)update((k<<1)+1,left,right,x);
	else
	{
		update(k<<1,left,mid,x);
		update((k<<1)+1,mid+1,right,x);
	}
}

ll query(int k,int left,int right)
{
	if(left <= node[k].l && right >= node[k].r)return node[k].sum;
	if(node[k].add)pushdown(k);
	int mid = (node[k].l+node[k].r)>>1;
	if(right <= mid)return query(k<<1,left,right);
	else if(left > mid)return query((k<<1)+1,left,right);
	else return (query(k<<1,left,mid)+query((k<<1)+1,mid+1,right));
}

void build(int k,int left,int right)
{
	node[k].l = left,node[k].r = right;
	node[k].add = 0;
	if(node[k].l == node[k].r)
	{
		node[k].sum = a[left];
		return;
	}
	int mid = (left+right)>>1;
	build(k<<1,left,mid);
	build((k<<1)+1,mid+1,right);
	node[k].sum = node[k<<1].sum + node[(k<<1)+1].sum;
}

int main()
{
	cin>>n;
	for(int i = 1;i <= n;i++)scanf("%d",&a[i]); 
	build(1,1,n);
	cin>>Q;
	for(int i = 1;i <= Q;i++)
	{
		int s,a,b,x;scanf("%d",&s);
		if(s == 1)
		{
			scanf("%d%d%d",&a,&b,&x);
			update(1,a,b,x);
		}
		else
		{
			scanf("%d%d",&a,&b);
			cout<<query(1,a,b)<<"\n";
		}
	}
	return 0;
}

你可能感兴趣的:(算法,线段树)