线段树——hdu1166敌兵布阵
一、题目回顾
题目链接:敌兵布阵
中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少人,例如Derek问:“Tidy,马上汇报第3个营地到第10个营地共有多少人!”Tidy就要马上开始计算这一段的总人数并汇报。但敌兵营地的人数经常变动,而Derek每次询问的段都不一样,所以Tidy不得不每次都一个一个营地的去数,很快就精疲力尽了,Derek对Tidy的计算速度越来越不满:"你个死肥仔,算得这么慢,我炒你鱿鱼!”Tidy想:“你自己来算算看,这可真是一项累人的工作!我恨不得你炒我鱿鱼呢!”无奈之下,Tidy只好打电话向计算机专家Windbreaker求救,Windbreaker说:“死肥仔,叫你平时做多点acm题和看多点算法书,现在尝到苦果了吧!”Tidy说:"我知错了。。。"但Windbreaker已经挂掉电话了。Tidy很苦恼,这么算他真的会崩溃的,聪明的读者,你能写个程序帮他完成这项工作吗?不过如果你的程序效率不够高的话,Tidy还是会受到Derek的责骂的.
每组数据第一行一个正整数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条命令
对于每个Query询问,输出一个整数并回车,表示询问的段中的总人数,这个数保持在int以内。
1 2 3 4 5 6 7 8 9 10
const int maxn = 150005; struct SegTreeNode
{
int val;
}segTree[maxn]; //定义线段树 void build(int root, int arr[], int istart, int iend)
{
if(istart == iend) //叶子节点
segTree[root].val = arr[istart];
else{
int mid = (istart + iend) / 2;
build(root*2, arr, istart, mid);//递归构造左子树
build(root*2+1, arr, mid+1, iend);//递归构造右子树
segTree[root].val = segTree[root*2].val + segTree[root*2+1].val;
}
} int query(int root, int nstart, int nend, int qstart, int qend)
{
//默认查询区间和当前节点区间有交集
if(qstart <= nstart && qend >= nend)
return segTree[root].val;
int mid = (nstart + nend) / 2;
int ans = 0;
if(qstart<=mid) ans += query(root*2, nstart, mid, qstart, qend);
if(qend>mid) ans += query(root*2+1, mid + 1, nend, qstart, qend);
return ans;
} void updateOne(int root, int nstart, int nend, int index, int addVal)
{
if(nstart == nend)
{
segTree[root].val += addVal;
return;
}
int mid = (nstart + nend) / 2;
if(index <= mid)//在左子树中更新
updateOne(root*2, nstart, mid, index, addVal);
else
updateOne(root*2+1, mid+1, nend, index, addVal);
segTree[root].val = segTree[root*2].val + segTree[root*2+1].val;
}
三、我的收获
①我们用数组来存储线段树时,有效空间为2n-1,实际空间却不止这么多,实际空间是满二叉树的节点数目。譬如,题目中要求N<=50000,一开始,我设置的maxn为50005,OJ报出了Runtime Error(ACCESS_VIOLATION),即出现数组越界,当将maxn设为150005时,成功AC。
②关于这种输入技巧,看代码!
四、题目代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 150005; struct SegTreeNode
{
int val;
}segTree[maxn]; //定义线段树 void build(int root, int arr[], int istart, int iend)
{
if(istart == iend) //叶子节点
segTree[root].val = arr[istart];
else{
int mid = (istart + iend) / 2;
build(root*2, arr, istart, mid);//递归构造左子树
build(root*2+1, arr, mid+1, iend);//递归构造右子树
segTree[root].val = segTree[root*2].val + segTree[root*2+1].val;
}
} int query(int root, int nstart, int nend, int qstart, int qend)
{
//默认查询区间和当前节点区间有交集
if(qstart <= nstart && qend >= nend)
return segTree[root].val;
int mid = (nstart + nend) / 2;
int ans = 0;
if(qstart<=mid) ans += query(root*2, nstart, mid, qstart, qend);
if(qend>mid) ans += query(root*2+1, mid + 1, nend, qstart, qend);
return ans;
} void updateOne(int root, int nstart, int nend, int index, int addVal)
{
if(nstart == nend)
{
segTree[root].val += addVal;
return;
}
int mid = (nstart + nend) / 2;
if(index <= mid)//在左子树中更新
updateOne(root*2, nstart, mid, index, addVal);
else
updateOne(root*2+1, mid+1, nend, index, addVal);
segTree[root].val = segTree[root*2].val + segTree[root*2+1].val;
} int main()
{
int T,n,arr[maxn],a,b,kase=0;
scanf("%d",&T);
while(T--){
kase++;
printf("Case %d:\n",kase);
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&arr[i]);
}
build(1,arr,1,n);
char ch[10];
while(scanf("%s",ch)&&ch[0]!='E'){
scanf("%d %d",&a,&b);
if(ch[0]=='Q'){
printf("%d\n",query(1,1,n,a,b));
}
else if(ch[0]=='A'){
updateOne(1,1,n,a,b);
}
else{
updateOne(1,1,n,a,-b);
}
}
}
return 0;
}
线段树——hdu1166敌兵布阵的更多相关文章
- 线段树 HDU-1166 敌兵布阵
敌兵布阵是一个线段树典题,题目如下(点此查看题目出处): Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国 ...
- 线段树 - HDU1166 - 敌兵布阵
2017-07-29 16:41:00 writer:pprp 线段树跟区间操作相关,想要在题目限定的时间内解决问题就需要用线段树这种数据结构来解决: 线段树是一种二叉平衡树 参考书目:张新华的< ...
- 线段树---HDU1166敌兵布阵
这个是线段树中最入门的题目,但是由于不了解线段树的概念,当然更不知道怎么样,所以觉得挺费劲,整了一会发现还是基本的思想,就是还是将一个线段继续分割,一直分割到不能分割,这道题目是知道多少个军营,也就是 ...
- (线段树)敌兵布阵--hdu--1166 (入门)
链接: http://acm.hdu.edu.cn/showproblem.php?pid=1166 自己第一次在没有看题解AC出来的线段树,写的可能不是太好,再贴个学长的代码,学习一下 发现自己的U ...
- 【算法系列学习】线段树vs树状数组 单点修改,区间查询 [kuangbin带你飞]专题七 线段树 A - 敌兵布阵
https://vjudge.net/contest/66989#problem/A 单点修改,区间查询 方法一:线段树 http://www.cnblogs.com/kuangbin/archive ...
- HDU-1166敌兵布阵(线段树)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submissi ...
- hdu1166 敌兵布阵(线段树 求区间和 更新点)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- HDU1166 敌兵布阵_线段树
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- hdu1166 敌兵布阵 线段树(区间更新)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
随机推荐
- Anaconda的使用—Spyder常用快捷键
Ctrl + 1: 注释/反注释 Ctrl + 4/5: 块注释/块反注释 Ctrl + L: 跳转到行号 Tab/Shift + Tab: 代码缩进/反缩进 Ctrl +I:显示帮助
- HDFS学习总结
1.什么是Hadoop 管理网络中跨多台计算机存储的文件系统称为分布式文件系统面临的挑战:使文件系统能容忍节点故障且不丢失任何数据不适合的特点:低时间延迟的数据访问&大量的小文件&多用 ...
- Mysql 查看连接数,状态,最大并发数
MySQL: ERROR 1040: Too many connections”的异常情况,造成这种情况的一种原因是访问量过高,MySQL服务器抗不住,这个时候就要考虑增加从服务器分散读压力:另一种原 ...
- thinkphp5一些文件夹用法
一.vendor通常放一些第三方的文件,如短信.支付宝等.用法: 1.在vendor中建一个文件夹: 2.在文件夹中新建一个类:主要命名空间(没有vendor ):如下面: 3.在控制器中调用,除了通 ...
- mysql导出数据库表名与字段信息
一.导出数据库表格信息 #mysql导出库的表格信息 SELECT A.TABLE_SCHEMA, A.TABLE_NAME, A.TABLE_ROWS, A.CREATE_TIME, A.TABLE ...
- 八、USB驱动分析
学习目标:分析USB驱动源码结构. 一.Windows下USB驱动理论问题 1. 当usb设备接入PC时,右下角弹出"发现AAA",并弹出对话框,提示安装驱动程序.没有驱动程序,W ...
- python基础,导入模块,if语句,while语句
python基础 python代码 变为字节码 变为机器码 最后执行执行‘文件名.py’文件时出现的‘文件名.pyc’文件为字节码 缓存机制 使用pycharm的时候在文件最开始添加下面这两行代码,中 ...
- 函数名前加 & 符号的深入理解 C++
#include <iostream> using namespace std; int& test_str() { ; return a; //通过返回 a 的地址来进行 值的返 ...
- 笔记-python-常见特殊变量
笔记-python-常见特殊变量 类似__xx,以双下划线开头的实例变量名,就变成了一个私有变量(private),只有内部可以访问,外部不能访问: 类似__xx__,以双下划线开头,并且以双下划线结 ...
- 利用JS调取电脑摄像头,实现拍照功能
1.调取电脑摄像头非常简单,看代码一幕了然 window.addEventListener("DOMContentLoaded", function() { var canvas ...