码迷,mamicode.com
首页 > 其他好文 > 详细

(hdu step 5.3.1)敌兵布阵(线段树:单点更新)

时间:2015-03-09 17:39:11      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:


题目:

敌兵布阵

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 312 Accepted Submission(s): 194
 
Problem Description
C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了。A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况。由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视。
中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少人,例如Derek问:“Tidy,马上汇报第3个营地到第10个营地共有多少人!”Tidy就要马上开始计算这一段的总人数并汇报。但敌兵营地的人数经常变动,而Derek每次询问的段都不一样,所以Tidy不得不每次都一个一个营地的去数,很快就精疲力尽了,Derek对Tidy的计算速度越来越不满:\\\\\\\"你个死肥仔,算得这么慢,我炒你鱿鱼!”Tidy想:“你自己来算算看,这可真是一项累人的工作!我恨不得你炒我鱿鱼呢!”无奈之下,Tidy只好打电话向计算机专家Windbreaker求救,Windbreaker说:“死肥仔,叫你平时做多点acm题和看多点算法书,现在尝到苦果了吧!”Tidy说:\\\\\\\"我知错了。。。\\\\\\\"但Windbreaker已经挂掉电话了。Tidy很苦恼,这么算他真的会崩溃的,聪明的读者,你能写个程序帮他完成这项工作吗?不过如果你的程序效率不够高的话,Tidy还是会受到Derek的责骂的.
 
Input
第一行一个整数T,表示有T组数据。
每组数据第一行一个正整数N(N<=50000),表示敌人有N个工兵营地,接下来有N个正整数,第i个正整数ai代表第i个工兵营地里开始时有ai个人(1<=ai<=50)。
接下来每行有一条命令,命令有4种形式:
(1) Add i j,i和j为正整数,表示第i个营地增加j个人(j不超过30)
(2)Sub i j ,i和j为正整数,表示第i个营地减少j个人(j不超过30);
(3)Query i j ,i和j为正整数,i<=j,表示询问第i到第j个营地的总人数;
(4)End 表示结束,这条命令在每组数据最后出现;
每组数据最多有40000条命令
 
Output

            对第i组数据,首先输出“Case i:”和回车,
对于每个Query询问,输出一个整数并回车,表示询问的段中的总人数,这个数最多不超过1000000。
 
Sample Input
1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End
 
Sample Output
Case 1:
6
33
59
 
Author
Windbreaker
 
 
Recommend
Eddy



题目分析:

                线段树。单点更新。


代码如下:

/*
 * a1.cpp
 *
 *  Created on: 2015年3月9日
 *      Author: Administrator
 */
#include <iostream>
#include <cstdio>

using namespace std;

const int maxn = 50001;//最大的节点数


struct node {//线段树区间结点
	int left;//区间的左结点
	int right;//区间有节点
	int sum;//整个区间的值

	/**
	 * 用于求区间的中间值
	 */
	int mid() {
		return (left + right) / 2;
	}
} tree[maxn * 4];//线段树的节点数是平常数组节点数的4倍

int ans;//用于存储查询时后的区间值

/**
 * 线段树的构造函数
 * left: 该区间的左端点
 * right: 该区间的右端点
 * rt: 该区间节点的编号
 */
void buildtree(int left, int right, int rt) {
	tree[rt].left = left;//该区间节点的左结点
	tree[rt].right = right;//该区间节点的右结点

	if (left == right) {//如果当前节点记录的区间只有一个值
		scanf("%d", &tree[rt].sum);//直接给当前节点复制
		return;
	}

	//否则,递归构造左右子树
	int mid = tree[rt].mid();
	buildtree(left, mid, rt * 2);
	buildtree(mid + 1, right, rt * 2 + 1);
	//当前节点的区间值 = 左孩子的区间值 + 右孩子的区间值
	tree[rt].sum = tree[rt * 2].sum + tree[rt * 2 + 1].sum;
}

/**
 * 在区间结点rt中 查询[L,R]的区间值,其中left是区间结点rt的左端点,
 * right是区间结点的右端点
 */
void query(int left, int right, int rt, int L, int R) {
	//如果要查找的区间包含了当前查找到的整个区间简洁点
	if (L <= left && right <= R) {
		ans += tree[rt].sum;//则加上当前的区间值

		return;
	}

	//否则按照左右子树来递归查找
	int mid = tree[rt].mid();
	if (R <= mid) {
		query(left, mid, rt * 2, L, R);
	} else if (mid < L) {
		query(mid + 1, right, rt * 2 + 1, L, R);
	} else {
		query(left, mid, rt * 2, L, R);
		query(mid + 1, right, rt * 2 + 1, L, R);
	}
}

/**
 * 给pos结点加上add
 */
void update(int left, int right, int rt, int pos, int add) {
	//如果找到了目标节点
	if (left == right) {
		tree[rt].sum += add;//则将add直接加到目标节点上

		return;
	}

	//如果没有按照左右子树来递归查找
	int mid = tree[rt].mid();
	if (pos <= mid) {
		update(left, mid, rt * 2, pos, add);
	} else {
		update(mid + 1, right, rt * 2 + 1, pos, add);
	}

	//最后更新当前节点的区间值  = 左孩子的区间值  + 右孩子的区间值
	tree[rt].sum = tree[rt * 2].sum + tree[rt * 2 + 1].sum;
}

int main() {
	int t;
	scanf("%d", &t);
	int k;
	for (k = 1; k <= t; ++k) {
		printf("Case %d:\n", k);

		int n;
		scanf("%d", &n);
		buildtree(1, n, 1);

		char str[10];
		while (scanf("%s", str) != EOF) {
			if (str[0] == ‘E‘) {
				break;
			}

			if (str[0] == ‘A‘) {
				int a, b;
				scanf("%d%d", &a, &b);

				update(1, n, 1, a, b);
			} else if (str[0] == ‘S‘) {
				int a, b;
				scanf("%d%d", &a, &b);
				update(1, n, 1, a, -b);
			} else if (str[0] == ‘Q‘) {
				ans = 0;
				int left;
				int right;
				scanf("%d%d", &left, &right);

				query(1, n, 1, left, right);

				printf("%d\n", ans);
			}
		}

	}

	return 0;
}








(hdu step 5.3.1)敌兵布阵(线段树:单点更新)

标签:

原文地址:http://blog.csdn.net/hjd_love_zzt/article/details/44156197

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!