HDU 1166 【线段树 || 树状数组,单点修改 维护区间和】
大概题意:
第一行一个整数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条命令
思路:类似于区间查询和区间修改等操作,操作数又较多的情况优先想线段树、树状数组等。而线段树和树状数组的相似之处在于二分思想的应用,不同的是前者直接二分,后者要转换为二进制间接对数组以一种特定的组合形式进行二分。
方法一:线段树,因为线段树又是一颗平衡二叉树,所以可以用二叉树的构建方法,在这里用的是结构数组的表示方法。
结点 :T[a, b] (a, b 表示区间 [a, b] , 其中 b-a 为长度 len )
线段树递归定义为:
若 len > 1 , 则 [a, (a+b)/2] 为 T 的左儿子, [(a+b)/2+1, b] 为 T 的右儿子。
若 len == 1, 则 T 为叶子节点。
复杂度:
线段树的深度不超过log2len, 线段树把区间上的任意一条线段都分成不超过 2log2len 条线段。所以线段树能在O(log2len) 时间内完成一条线段的插入, 删除, 和查找等工作。
入门题,AC code:
///HDU 1166 线段树
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std; struct
{
int a, b, sum; ///左端点, 右端点, 区间和
}t[140000];
int people[50010], SUM; ///每个营地的人数 void make(int x, int y, int num) ///x为左端点,y为右端点,num为数组下标
{
t[num].a = x; ///确定左端点为x
t[num].b = y; ///确定右端点为y if(x == y) ///左端点等于右端点,说明到达叶子结点
t[num].sum = people[y];
else
{
make(x, (x+y)/2, num+num); ///递归构造左子树
make((x+y)/2+1, y, num+num+1); ///递归构造右子树
t[num].sum = t[num+num].sum + t[num+num+1].sum;
///父结点的区间和等于子树的区间和之和,因为区间被分成两半
}
} void add(int i, int j, int num) ///第i个堡垒加j艘船,初始nun为1,即从根结点开始
{
t[num].sum+=j;
if(t[num].a == i && t[num].b == i) ///找到叶子结点,返回
return;
if(i > (t[num].a+t[num].b)/2) ///点i在该区间的右边
add(i, j, num+num+1); ///递归进右结点
else
add(i, j, num+num); ///否则递归进左结点
} void sub(int i, int j, int num) ///第i个堡垒减j艘船
{
t[num].sum-=j;
if(t[num].a == i && t[num].b == i) ///找到叶子结点,返回
return;
if(i > (t[num].a+t[num].b)/2)
sub(i, j, num+num+1);
else
sub(i, j, num+num);
} void query(int i, int j, int num) ///求i到j的总飞船长度, num初始化为1,即从根节点开始
{
if(i <= t[num].a && j >= t[num].b)
SUM+=t[num].sum;
else
{
int mid = (t[num].a + t[num].b)/2;
if(i > mid)
query(i, j, num+num+1);
else if(j <= mid)
query(i, j, num+num);
else
{
query(i, j, num+num);
query(i, j, num+num+1);
}
}
} int main()
{
int N, T;
char command[6];
scanf("%d", &T);
int j = 0;
while(T--)
{
int temp, a, b;
scanf("%d", &N);
for(int i = 1; i <= N; i++)
{
scanf("%d", &people[i]);
}
make(1, N, 1); printf("Case %d:\n", ++j);
while(cin >> command)
{
if(strcmp(command, "End") == 0) break;
else if(strcmp(command, "Query") == 0)
{
cin >> a >> b;
SUM = 0;
query(a, b, 1);
cout << SUM << endl;
}
else if(strcmp(command, "Add") == 0)
{
cin >> a >> b;
add(a, b, 1);
}
else if(strcmp(command, "Sub") == 0)
{
cin >> a >> b;
sub(a, b, 1);
}
}
}
return 0;
}
方法二:树状数组
关键在于二进制下的二分思想,理解通过 lowbit (求最低位1)进行数组关系的递推。
Ac code:
///HDU 1166 树状数组
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std; const int MAXN = 50005; int N;
int c[MAXN]; ///树状数组 int lowbit(int x) ///位运算,取最低位1,用于后面树状数组下标的二分
{
return x&(-x);
} void add(int i, int value) ///单点加,由上自下更新树状数组
{
while(i <= N)
{
c[i]+=value;
//printf("%d %d\n", i, c[i]);
i+=lowbit(i);
}
} int sum(int i) ///求前缀和
{
int sum = 0;
while(i > 0)
{
sum+=c[i];
i-=lowbit(i);
}
return sum;
} int main()
{
int T;
char command[6];
scanf("%d", &T);
int j = 0;
while(T--)
{
int temp, a, b, d;
scanf("%d", &N);
memset(c, 0, sizeof(c));
for(int i = 1; i <= N; i++)
{
scanf("%d", &d);
add(i, d);
} ///debug
/*
for(int i = 1; i <= N; i++)
printf("%d ", c[i]);
puts("");
*/
printf("Case %d:\n", ++j);
while(cin >> command)
{
if(strcmp(command, "End") == 0) break;
else if(strcmp(command, "Query") == 0)
{
cin >> a >> b;
int SUM = 0;
SUM = sum(b) - sum(a-1);
cout << SUM << endl;
}
else if(strcmp(command, "Add") == 0)
{
cin >> a >> b;
add(a, b);
}
else if(strcmp(command, "Sub") == 0)
{
cin >> a >> b;
add(a, -b);
}
}
}
return 0;
}
HDU 1166 【线段树 || 树状数组,单点修改 维护区间和】的更多相关文章
- HDU 1166 敌兵布阵 (树状数组 单点修改+区间查询)
题目链接 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和T ...
- 【算法系列学习】线段树vs树状数组 单点修改,区间查询 [kuangbin带你飞]专题七 线段树 A - 敌兵布阵
https://vjudge.net/contest/66989#problem/A 单点修改,区间查询 方法一:线段树 http://www.cnblogs.com/kuangbin/archive ...
- Libre OJ 130、131、132 (树状数组 单点修改、区间查询 -> 区间修改,单点查询 -> 区间修改,区间查询)
这三题均可以用树状数组.分块或线段树来做 #130. 树状数组 1 :单点修改,区间查询 题目链接:https://loj.ac/problem/130 题目描述 这是一道模板题. 给定数列 a[1] ...
- 牛客小白月赛6 F 发电 树状数组单点更新 求区间乘积 模板
链接:https://www.nowcoder.com/acm/contest/136/F来源:牛客网 HA实验是一个生产.提炼“神力水晶”的秘密军事基地,神力水晶可以让机器的工作效率成倍提升. ...
- HUST——1106xor的难题之二(异或树状数组单点修改和区间查询)
1106: xor的难题之二 时间限制: 2 Sec 内存限制: 128 MB 提交: 8 解决: 3 题目描述 上次Alex学长的问题xor难题很简单吧,现在hkhv学长有个问题想问你们. 他现 ...
- HDU 1754 I Hate It 【线段树单点修改 维护区间最大值】
题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1754 I Hate It Time Limit: 9000/3000 MS (Java/Others ...
- TZOJ 2725 See you~(二维树状数组单点更新区间查询)
描述 Now I am leaving hust acm. In the past two and half years, I learned so many knowledge about Algo ...
- hdu 1166 线段树(sum+单点修改)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- hdu 2642二维树状数组 单点更新区间查询 模板题
二维树状数组 单点更新区间查询 模板 从零开始借鉴http://www.2cto.com/kf/201307/227488.html #include<stdio.h> #include& ...
随机推荐
- Hadoop实战之一~Hadoop概述
对技术,我还是抱有敬畏之心的. Hadoop概述 Hadoop是一个开源分布式云计算平台,基于Map/Reduce模型的,处理海量数据的离线分析工具.基于Java开发,建立在HDFS上,最早由Goog ...
- JQuery对数组的一些操作总结
JQuery对数组的处理非常便捷并且功能强大齐全,一步到位的封装了很多原生js数组不能企及的功能.下面来看看JQuery数组的强大之处在哪. $.each(array, [callback]) 遍历 ...
- Java API 之 Properties 类
1.简介 在项目中我们经常看到一种格式极其干净的配置文件,如:config.properties.在Java的体系结构中也提供了API对properties文件进行读取和写入等操作,即:Propert ...
- Collatz 序列、逗号代码、字符图网格
1.collatz序列 编写一个名为 collatz()的函数,它有一个名为 number 的参数.如果参数是偶数, 那么 collatz()就打印出 number // 2,并返回该值.如果 num ...
- JBPM学习第2篇:为Eclipse添加JBPM开发支持
1.Eclipse添加JBoss支持插件 参考:Eclipse添加JBoss支持 若已安装,直接跳过! 2.Eclipse添加Drools插件 jbpm-installer-full解压后的文件夹中找 ...
- K2P刷机教程转自恩山磨人的小妖精
K2P刷机指南说明 K2P MTK版发布之初用的是22.5.7.85, 这个版本官改和高恪K2P固件都可以从斐讯固件基础上直接升级, 是所谓直刷.但好景不长, 之后的版本比如22.5.17.33就改了 ...
- Live2D 博客页面添加板娘
偶然看到了live2d,神奇的二次元呀 在页脚Html代码中添加如下代码即可: <link rel="stylesheet" type="text/css" ...
- 动态赋值poster,无法显示
vue操作video的poster属性时,动态给poster赋值,在chrome下是无法显示的 解决办法 在赋值后,找到video元素.load()下就会看到封面图了
- Day04——Python模块
一.模块简介 模块是实现了某个功能的代码集合,比如几个.py文件可以组成代码集合即模块.其中常见的模块有os模块(系统相关),file模块(文件操作相关) 模块主要分三类: 自定义模块 :所谓自定义模 ...
- VMWARE里安装时出现'SMBus Host Controller not enabled'
在虚拟机上运行Linux内核版本为4.7或以上的系统都在安装过程中或在启动时会因为加载intel_powerclamp驱动而导致崩溃.解决办法:1.在启动Ubuntu的时候按住左Shift键:2.Ub ...