HDU 1166 敌兵布阵 线段树单点更新求和
中文题,线段树入门题,单点更新求和,建一棵树就可以了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define N 50005
using namespace std;
int data[N];
struct Tree
{
int l,r,sum;
}tree[N*];
void build(int root,int l,int r)
{
tree[root].l=l;
tree[root].r=r;
if(l==r)
{
tree[root].sum=data[l];
return;
}
int mid=(l+r)>>;
build(root<<,l,mid);
build(root<<|,mid+,r);
tree[root].sum=tree[root<<].sum+tree[root<<|].sum;
}
void update(int root,int pos,int val)
{
if(tree[root].l==tree[root].r)
{
tree[root].sum=val;
return;
}
int mid=(tree[root].l+tree[root].r)>>;
if(pos<=mid) update(root<<,pos,val);
else update(root<<|,pos,val);
tree[root].sum=tree[root<<].sum+tree[root<<|].sum;
}
int query(int root,int l,int r)
{
if(l<=tree[root].l&&r>=tree[root].r) return tree[root].sum;
int mid=(tree[root].l+tree[root].r)>>,ret=;
if(l<=mid) ret+=query(root<<,l,r);
if(r>mid) ret+=query(root<<|,l,r);
return ret;
}
int main()
{
int n,t,cas=;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d",&data[i]);
build(,,N);
int a,b;
char c[];
printf("Case %d:\n",cas++);
while(scanf("%s",c)!=EOF)
{
if(strcmp(c,"End")==) break;
scanf("%d%d",&a,&b);
if(strcmp(c,"Add")==)
{
data[a]+=b;
update(,a,data[a]);
}
else if(strcmp(c,"Sub")==)
{
data[a]-=b;
update(,a,data[a]);
}
else if(strcmp(c,"Query")==)
{
if(a>b) swap(a,b);
printf("%d\n",query(,a,b));
}
}
}
return ;
}
带注释版:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define N 50005
using namespace std;
int num[N];
struct Tree
{
int l; //左端点
int r; //右端点
int sum; //总数
} tree[N*]; // 总线段的长度为 N,开数组的话一般开到 N 的四倍
void build(int root,int l,int r) // root 表示根节点 ,他的区间范围【l,r】
{
tree[root].l=l;
tree[root].r=r;
if(tree[root].l==tree[root].r) // 当左右端点相等时就是叶子节点
{
tree[root].sum=num[l]; // 赋除值
return; // 递归出口
}
int mid=(l+r)/;
build(root<<,l,mid); // k<<1 相等于 k*2 即是他的左孩子
build(root<<|,mid+,r); // k<<1|1 相当于 k*2+1 ,即是他的右孩子
tree[root].sum = tree[root<<].sum + tree[root<<|].sum; // 父亲的 sum = 左孩子的 sum+ 右孩子的 sum
}
void update(int root,int pos,int val) // root 是根节点,pos,val 表示:我们要跟新在 pos 点出的值更新为 val
{
if(tree[root].l==tree[root].r) // 如果是叶子节点,即是 pos 对应的位置
{
tree[root].sum=val; // 更新操作
return; // 递归出口
}
int mid=(tree[root].l + tree[root].r)/;
if(pos<=mid) // 如果 pos 点是在 root 对应的左孩子的话,就调用 update(k<<1,pos,val);在左孩子里找
update(root<<,pos,val);
else
update(root<<|,pos,val);
tree[root].sum = tree[root<<].sum + tree[root<<|].sum; // 父亲的 sum = 左孩子的 sum+ 右孩子的 sum
}
int query(int root,int L,int R) // root 表示根节点,[L,R]表示要查询的区间
{
if(L<=tree[root].l&&R>=tree[root].r) // [L,R]要查询的区间 包含 root 节点表示的区间直接返回 root 节点的 sum 值
return tree[root].sum;
int mid=(tree[root].l + tree[root].r)/,ret=;
if(L<=mid) ret+=query(root<<,L,R); // 查询 root 节点的左孩子
if(R>mid) ret+=query(root<<|,L,R); // 查询 root 节点的右孩子
return ret; // 返回
}
int main()
{
int ca,cas=,n,Q,a,b;
char str[];
scanf("%d",&ca);
while(ca--)
{
scanf("%d",&n);
for(int i=; i<=n; i++)
scanf("%d",&num[i]); // 表示在 i 点的兵力数量
build(,,N); // 构造线段树根节点 1,表示的区间范围【1 ,N】
printf("Case %d:\n",cas++);
while(scanf("%s",str),strcmp(str,"End"))
{
scanf("%d%d",&a,&b);
if(strcmp(str,"Query")==)
{
if(a>b) swap(a,b); // 查询的区间 【a,b】
printf("%d\n",query(,a,b)); //输出查询结果
}
else if(strcmp(str,"Add")==)
{
num[a]=num[a]+b;
update(,a,num[a]); // 跟新 a 点值为 num[a]
}
else if(strcmp(str,"Sub")==)
{
num[a] = num[a]-b;
update(,a,num[a]);
}
}
}
return ;
}
HDU 1166 敌兵布阵 线段树单点更新求和的更多相关文章
- HDU.1166 敌兵布阵 (线段树 单点更新 区间查询)
HDU.1166 敌兵布阵 (线段树 单点更新 区间查询) 题意分析 加深理解,重写一遍 代码总览 #include <bits/stdc++.h> #define nmax 100000 ...
- HDU 1166 敌兵布阵(线段树单点更新,板子题)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- HDU 1166 敌兵布阵(线段树单点更新)
敌兵布阵 单点更新和区间更新还是有一些区别的,应该注意! [题目链接]敌兵布阵 [题目类型]线段树单点更新 &题意: 第一行一个整数T,表示有T组数据. 每组数据第一行一个正整数N(N< ...
- HDU 1166 敌兵布阵(线段树单点更新,区间查询)
描述 C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况 ...
- 【原创】hdu 1166 敌兵布阵(线段树→单点更新,区间查询)
学习线段树的第三天...真的是没学点啥好的,又是一道水题,纯模板,我个人觉得我的线段树模板还是不错的(毕竟我第一天相当于啥都没学...找了一整天模板,对比了好几个,终于找到了自己喜欢的类型),中文题目 ...
- hdu 1166 敌兵布阵 线段树 点更新
// hdu 1166 敌兵布阵 线段树 点更新 // // 这道题裸的线段树的点更新,直接写就能够了 // // 一直以来想要进线段树的坑,结果一直没有跳进去,今天算是跳进去吧, // 尽管十分简单 ...
- HDU 1166 敌兵布阵 <线段树 单点修改 区间查询>
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- HDU 1754 线段树 单点跟新 HDU 1166 敌兵布阵 线段树 区间求和
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- hdu 1166 敌兵布阵 线段树区间修改、查询、单点修改 板子题
题目链接:敌兵布阵 题目: C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视 ...
随机推荐
- [原创]vscode初体验
这段时间,在网上看见很多从.net转java的,为什么会造成这样的情况,我感觉有几点 1. 微软在中国的生态不好,死要钱,很多公司都不想花这部分钱 2. 做.net开发人,工资普遍较低 前言 闲聊 ...
- jq方法中 $(window).load() 与 $(document).ready() 的区别
通过自学进入了前端的行列,只知道在js中,一开头就写一个: window.onload = function(){ //doing sth} 然后所有的乱七八糟的代码全塞里面,大概知道window.o ...
- matlab中数组创建方法
创建数组可以使用 分号 : 逗号, 空格 数组同行用 逗号,或空格分割 不同行元素用 分号: clc; a = [ ]; b1 = a();%第3个元素 b2 = a(:)%第2//4个元素 b3 ...
- Matlab中^2和.^2的区别
矩阵a a^2 -- 两个矩阵相乘 a.^2 -- 表示 矩阵对应位置相乘 如下: a=[ 1,2,3 4,5,6 7,8,9]; disp(a); disp(a^2); disp(a.^2); ...
- 小猪cms之怎样查询绑定的微网站模板
微网站内容页面url g=Wap&m=Index&a=content (g=Wap)模块路径对应路径:\PigCms\Lib\Action\Wap (m=Index)控制文件对应文件: ...
- 封装js的部分兼容性
//获取标签的内容(兼容所有浏览器)function getInnerText(element) { //能力检测(先判断如果这个能力有这个) if(typeof element.innerText ...
- HDU 5944 Fxx and string(暴力/枚举)
传送门 Fxx and string Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Othe ...
- js小功能整理
/** * 判断是否包含字符串某字符串 * @param {[type]} str [被检测的字符串] * @param {[type]} substr [检测是否含有的字符串] * @return ...
- widows和Linux java加密注意事项
/** * @Title: EncrypAES.java * @Package com.weidinghuo.payment.util * @Description: TODO(用一句话描述该文件做什 ...
- 回顾Spirng ioc 控制反转
Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的.结合网上对Spring Ioc的理解,回顾一下自 ...