[HDU]1166敌兵布阵<静态线段树>
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166
题目大意:给出n个点,每个点有一个值,现在有三种操作,
1.在i点加上j
2.在i点减去j
3.查询i,j区间总和
这其实是一道非常裸的线段树,但是我还是卡了好久,结果最后发现竟然是自己的freopen和代码习惯惹的祸。这道题我用了两种方法,一种是比较常规的版本,一种是不用结构体的静态树
首先来看一个常规的代码(带结构体)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<stack>
#define maxn 500005
#define lson pos<<1
#define rson pos<<1|1
using namespace std; struct node{
int l,r,sum;
}e[maxn]; int n,a[maxn],t; void build(int l,int r,int pos)
{
e[pos].l=l;e[pos].r=r;
if(l==r)e[pos].sum=a[l];
else{
int mid=(l+r)>>;
build(l,mid,lson);build(mid+,r,rson);
e[pos].sum=e[lson].sum+e[rson].sum;//pushup操作
}
} void add(int k,int x,int pos)
{
int l=e[pos].l,r=e[pos].r;
e[pos].sum+=x;
int mid=(l+r)>>;
if(l==r&&l==k)
{
return;
}else{
if(k<=mid)add(k,x,lson);
else add(k,x,rson);
}
} void sub(int k,int x,int pos)
{
e[pos].sum-=x;
int l=e[pos].l;int r=e[pos].r;
int mid=(l+r)>>;
if(l==r&&l==k)
{
return;
}else{
if(k<=mid)sub(k,x,lson);
else sub(k,x,rson);
}
} int summ;
void query(int l,int r,int pos)
{
if(e[pos].l>=l&&e[pos].r<=r){
summ+=e[pos].sum;
}
else{
int mid=(e[pos].l+e[pos].r)/;
if(mid>=r){
query(l,r,lson);
}
else{
if(l>mid)query(l,r,rson);
else{
query(l,r,lson);query(l,r,rson);
}
}
}
} char ch[];
int main()
{
scanf("%d",&t);int y=;
while(t--)
{
y++;
printf("Case %d:\n",y);
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
scanf("\n");
build(,n,); while()
{ scanf("%s",ch);
if(ch[]=='E')break;
if(ch[]=='A'){
int x,y;
scanf("%d%d",&x,&y);
add(x,y,);
}
if(ch[]=='S')
{
int x,y;
scanf("%d%d",&x,&y);
sub(x,y,);
}
if(ch[]=='Q')
{ summ=;
int x,y;
scanf("%d%d",&x,&y);
query(x,y,);
printf("%d\n",summ);
} } }
}
打完这个代码其实不难发现,每一个pos(节点)的左右区间其实是固定的,而且还可以推出来,画个图分析一下

红色数字为pos,黑色为l,r,可以发现其实pos对应的l,r不会变,就是一棵静态树,
所以我们就可以不用结构体,只用看一个sum数组就可以解决了
来看一看代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define lson pos<<1
#define rson pos<<1|1
#define maxn 500005
using namespace std; int sum[maxn<<];
int a[maxn],n,m,t;
char ch[]; void pushup(int pos)
{
sum[pos]=sum[lson]+sum[rson];
} void build(int l,int r,int pos)
{
if(l==r){sum[pos]=a[l];return;}
int mid=(l+r)/;
build(l,mid,lson);
build(mid+,r,rson);
pushup(pos);
} void add(int k,int x,int pos,int l,int r)
{
if(l==r){sum[pos]+=x;return;}
int mid=(l+r)>>;
if(k<=mid)add(k,x,lson,l,mid);
else add(k,x,rson,mid+,r);
pushup(pos);
} void sub(int k,int x,int pos,int l,int r)
{
if(l==r){sum[pos]-=x;return;}
int mid=(l+r)>>;
if(k<=mid)sub(k,x,lson,l,mid);
else sub(k,x,rson,mid+,r);
pushup(pos);
} int query(int al,int ar,int l,int r,int pos)
{
if(al<=l&&r<=ar)return sum[pos];
int mid=(l+r)>>,s=;
if(al<=mid)s+=query(al,ar,l,mid,lson);
if(ar>mid) s+=query(al,ar,mid+,r,rson);
return s;
} int main()
{
scanf("%d",&t);int y=;
while(t--)
{
cout<<"Case "<<++y<<":"<<endl;
memset(sum,,sizeof(sum));
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
build(,n,);
while()
{
scanf("%s",ch);
int x,y;
if(ch[]=='E')break;
if(ch[]=='A'){
scanf("%d%d",&x,&y);
add(x,y,,,n);
}
if(ch[]=='S')
{
scanf("%d%d",&x,&y);
sub(x,y,,,n);
}
if(ch[]=='Q')
{
scanf("%d%d",&x,&y);
printf("%d\n",query(x,y,,n,));
}
}
}
}
PS:诸位OIer打代码特别是函数时要注意声明的左右点和pos的位置关系,要一一对应,不然就像我一样会调试一天
[HDU]1166敌兵布阵<静态线段树>的更多相关文章
- hdu 1166敌兵布阵(线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) M ...
- hdu 1166 敌兵布阵 (线段树单点更新)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) ...
- HDU 1166 敌兵布阵(线段树/树状数组模板题)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- HDU 1166——敌兵布阵——————【线段树单点增减、区间求和】
敌兵布阵 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status ...
- HDU 1166 敌兵布阵 【线段树-点修改--计算区间和】
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- hdu 1166 敌兵布阵(线段树区间求和)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- HDU 1166 敌兵布阵(线段树模板题)
题目链接: 传送门 敌兵布阵 Time Limit: 2000MS Memory Limit: 32768 K Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头 ...
- hdu 1166 敌兵布阵【线段树】(求给定区间和)
题目链接:https://vjudge.net/contest/182746#problem/B 敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) ...
- HDU 1166 敌兵布阵 (线段树模版题)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
随机推荐
- 解决vue2.0下IE浏览器白屏问题
公司新开发的项目需要兼容到IE9+ 就在index.html页面加入 <meta http-equiv="X-UA-Compatible" content="IE= ...
- FC及BFC
1.什么是FC 2.BFC块级格式化上下文(Block formatting context) Box 是 CSS 布局的对象和基本单位, 直观点来说,就是一个页面是由很多个 Box 组成的.元素的类 ...
- PAT-字符串处理-B 1002 写出这个数 (20分)
题目: 思路: 先用字符串数组存储输入数字,然后依据num[i]-'0'对输入数字求和.然后对求和后的数字,进行分割,存储到数组中,然后遍历数组,依据存储汉语拼音的字符串二维数组进行输出 注意点: 注 ...
- Rust入坑指南:智能指针
在了解了Rust中的所有权.所有权借用.生命周期这些概念后,相信各位坑友对Rust已经有了比较深刻的认识了,今天又是一个连环坑,我们一起来把智能指针刨出来,一探究竟. 智能指针是Rust中一种特殊的数 ...
- Anroid关于fragment控件设置长按事件无法弹出Popupwindows控件问题解决记录
一.问题描述 记录一下最近在安卓的gragment控件中设置长按事件遇见的一个坑!!! 在正常的activity中整个活动中设置长按事件我通常实例化根部局,例如LinearLayout ...
- Ansible-免密登录与主机清单Inventory
Ansible的指定用户与密码登录.免密登录.指定ssh端口以及主机清单Inventory配置 在实际使用中并不需要对ansible配置进行修改,或者说只有需要的时候才修改ansible配置. 添加用 ...
- 如何创建一个自定义的`ErrorHandlerMiddleware`方法
在本文中,我将讲解如何通过自定义ExceptionHandlerMiddleware,以便在中间件管道中发生错误时创建自定义响应,而不是提供一个"重新执行"管道的路径. 作者:依乐 ...
- C++ 选择排序的理解
#include<stdio.h> #include <iostream> using namespace std; void swap(int *a, int *b) //元 ...
- swagger2 Illegal DefaultValue null for parameter type integer
问题,为了方便调试,引入了swagger2,但是在第一次访问的时候总是报 Illegal DefaultValue null for parameter type integer 让人看着很不输入 定 ...
- 初识Flask、快速启动
目录 一.初识Flask 1.1 什么是flask? 1.2 为什么要有flask? 二.Flask快速启动 一.初识Flask 1.1 什么是flask? Flask 本是作者 Armin Rona ...