PKU 3468 A Simple Problem with Integers

题目:http://poj.org/problem?id=3468

题意:有N个整数,有两个操作,一个是对给定的区间增加值,一个是查询给定区间的和

#include <stdio.h>
const int maxn=100000;
struct SegmentTree
{
	int l, r;
	long long sum, lazy;
}st[maxn<<2];
long long z[maxn+10], ans, c;
int n, q, a, b;
char ch[3];
void BuildTree(int v, int left, int right)
{
	st[v].l=left, st[v].r=right, st[v].lazy=0;
	if (left==right)
	{
		st[v].sum=z[left];
		return;
	}
	int lc=v<<1;
	int rc=lc+1;
	int mid=(left+right)>>1;
	BuildTree(lc, left, mid);
	BuildTree(rc, mid+1, right);
	st[v].sum=st[lc].sum+st[rc].sum;
}
void Insert(int left, int right, int v, long long x)
{
	if (st[v].l==left&&st[v].r==right)
	{
		st[v].lazy+=x;
		return;
	}
	int lc=v<<1;
	int rc=lc+1;
	int mid=(st[v].l+st[v].r)>>1;
	st[v].sum+=(x*(right-left+1));
	if (left>mid) Insert(left, right, rc, x);
	else if (right<=mid) Insert(left, right, lc, x);
	else
	{
		Insert(left, mid, lc, x);
		Insert(mid+1, right, rc, x);
	}
}
long long Query(int left, int right, int v)
{
	if (st[v].l==left&&st[v].r==right)
	{
		ans+=st[v].sum+st[v].lazy*(right-left+1);
		return ans;
	}
	int lc=v<<1;
	int rc=lc+1;
	int mid=(st[v].l+st[v].r)>>1;
	st[v].sum+=st[v].lazy*(st[v].r-st[v].l+1);
	st[lc].lazy+=st[v].lazy, st[rc].lazy+=st[v].lazy;
	st[v].lazy=0;
	if (left>mid) Query(left, right, rc);
	else if (right<=mid) Query(left, right, lc);
	else Query(left, mid, lc)+Query(mid+1, right, rc);
}
int main()
{
	//freopen("in.txt", "r", stdin);
	while (scanf("%d %d", &n, &q)==2)
	{
		for (int i=1; i<=n; i++) scanf("%lld", &z[i]);
		BuildTree(1, 1, n);
		for (int i=0; i<q; i++)
		{
			scanf("%s", ch);
			if (ch[0]=='C')
			{
				scanf("%d %d %lld", &a, &b, &c);
				Insert(a, b, 1, c);
			}
			else
			{
				scanf("%d %d", &a, &b);
				ans=0;
				printf("%lld\n", Query(a, b, 1));
			}
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值