swust-Deposit(0197)(线段树)

哆啦A梦喜欢收集古钱,在他家里有N个存钱罐,编号1..N。一天哆啦A梦闲的发慌,于是拿出他的古钱来玩。他玩钱要么把钱从某个罐中拿出,要么把钱放入某个罐中(假设除了存钱罐中的古钱,现在哆啦A梦拥有无限的古钱,不会出现想放入古钱却没有古钱的尴尬局面)。
Description
数据有多组, 
第一行是一个正整数N,1≤ N ≤100000,表示有N个存钱罐。 
第二行有N个正整数Ai(0≤ Ai ≤100),表示第i个存钱罐中已经有的古钱的个数。 
接下来是一个正整数T,1≤ T ≤100000。 
接下来的T行,每行有3个参数:op l r。 
1.op为"MOV",表示从l号存钱罐中取出r个古钱(1≤ r ≤10,1≤ l ≤N)。 
2.op为"ADD",表示哆啦A梦的往l号存钱罐中放入r个古钱(1≤ r ≤10,1≤ l ≤N)。 
3.op为"QUE",表示哆啦A梦希望知道在l,r之间(包括端点)的总的古钱个数(1≤ l, r ≤N)。 
4.op为"MAX",表示哆啦A梦希望知道在l,r之间(包括端点)的存钱罐中,含有最多古钱的存钱罐中的古钱个数(1≤ l, r ≤N)。 

当N为非正数的时候程序停止。 
Input
如上要求输出。
Output
1
2
3
4
5
6
7
8
9
10
1
30
5
MOV 1 1
QUE 1 1
ADD 1 12
MAX 1 1
QUE 1 1
-1
Sample Input
1
2
3
4
29
41
41
Sample Output
数据规模十分庞大,请适当选择您的输入输出函数.
/*
 *
 题解:
 线段树,本题有个坑就是查询的时候l可能大于r,要判断一下,本人就runtime  error了好几次,真是菜(*+﹏+*)

 */



#include <stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<iostream>
#include<string.h>
using namespace std;
int n;
struct node
{
	int l, r, sum;
	int mark;
	int _max;
}tree[4 * 100005];

void build(int l, int r, int i)
{
	tree[i].l = l;
	tree[i].r = r;
	tree[i].sum = tree[i]._max = 0;
	tree[i].mark = 0;
	if (l == r)
	{
		scanf("%d", &tree[i].sum);
		tree[i]._max = tree[i].sum;
		return;
	}
	int mid = (l + r) / 2;
	build(l, mid, i * 2);
	build(mid + 1, r, i * 2 + 1);
	tree[i].sum = tree[i * 2].sum + tree[i * 2 + 1].sum;
	tree[i]._max = max(tree[i * 2]._max, tree[i * 2 + 1]._max);

}

void add(int num ,int i, int k)
{
	if (tree[i].l == tree[i].r&&tree[i].l == num)
	{
		tree[i].sum += k;
		tree[i]._max = tree[i].sum;
		return;
	}
	int mid = (tree[i].l + tree[i].r) / 2;
	if (num <= mid)
	{
		add(num, i * 2, k);
	}
	else
	{
		add(num, i * 2 + 1, k);
	}

	tree[i].sum = tree[i * 2].sum + tree[i * 2 + 1].sum;
	tree[i]._max = max(tree[i * 2]._max, tree[i * 2 + 1]._max);
}

int Findsum(int l, int r, int i)
{
	if (l == tree[i].l&&r == tree[i].r)
	{
		return tree[i].sum;
	}
	int mid = (tree[i].l + tree[i].r) / 2;

	if (r <= mid)
	{
		return Findsum(l, r, i * 2);
	}
	else if (l > mid)
	{
		return Findsum(l, r, i * 2 + 1);
	}
	else
	{
		return Findsum(l, mid, i * 2) + Findsum(mid + 1, r, i * 2 + 1);
	}
}

int FindMax(int l, int r, int i)
{
	if (l == tree[i].l&&r == tree[i].r)
	{
		return tree[i]._max;
	}
	int mid = (tree[i].l + tree[i].r) / 2;
	if (r <= mid)
	{
		return FindMax(l, r, i * 2);
	}
	else if (l > mid)
	{
		return FindMax(l, r, i * 2 + 1);
	}
	else
	{
		return max(FindMax(l, mid, i * 2), FindMax(mid + 1, r, i * 2 + 1));
	}
}


int main()
{
	while (cin >> n&&n > 0)
	{
		build(1, n, 1);
		int t;
		cin >> t;
		char str[10];
		while (t--)
		{
			int l, r;
			scanf("%s", str);
			scanf("%d %d", &l, &r);
			if (strcmp(str, "MOV") == 0)
			{
				add(l,1, -r);
			}
			else if (strcmp(str, "ADD") == 0)
			{
				add(l, 1, r);
			}
			else if (strcmp(str, "QUE") == 0)
			{
				if (l > r)
				{
					swap(l, r);
				}
					printf("%d\n", Findsum(l, r, 1));
			}
			else if (strcmp(str, "MAX") == 0)
			{
				if (l > r)
				{
					swap(l, r);
				}
					printf("%d\n", FindMax(l, r, 1));
			}


		}
	}


	return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值