[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 ...
随机推荐
- Nuts.js01
1.简介 Vue ssr框架.支持vue2,vue-router,vuex,vue server render, vue meta 2.基本使用: vue init nuxt-community/ko ...
- 基础JavaScript练习(三)总结
任务目的 实践JavaScript数组.字符串相关操作 任务描述 基于任务四进行升级 将新元素输入框从input改为textarea 允许一次批量输入多个内容,格式可以为数字.中文.英文等,可以通过用 ...
- mongoose .find().limit()返回undefined
当我们使用mongoose的find方法查询数据库的同时,可以使用limit方法来指定返回数据的条数. limit方法基本语法如下所示: >db.COLLECTION_NAME.find().l ...
- SpringBoot图文教程14—SpringBoot集成EasyExcel「上」
有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...
- frida入门总结
一.Frida概述 Frida是一款轻量级HOOK框架,可用于多平台上,例如android.windows.ios等. frida分为两部分,服务端运行在目标机上,通过注入进程的方式来 ...
- 026.掌握Service-外部访问
一 集群外部访问 由于Pod和Service都是Kubernetes集群范围内的虚拟概念,所以集群外的客户端默认情况,无法通过Pod的IP地址或者Service的虚拟IP地址:虚拟端口号进行访问.通常 ...
- linux firewalld 防火墙操作命令
查看防火墙的状态systemctl status firewalldTomcat默认使用8080端口,如果防火墙开启,需要开通8080端口firewall-cmd --zone=public --ad ...
- Java集合02——三分钟了解你必须掌握的两个Set
上一篇文章我们说到了 List ,本章开始,我们将继续讲解Set相关的知识.关注公众号「Java面典」了解更多 Java 知识点. Set 是一个无重复对象的集合类.值的重复与否是根据对象的 hash ...
- vue基础回顾 router
vue-router 1. 底层原理 hash 或者h5 histroy(有兼容性) 2. 使用的时候Vue需要引入VueRouter Vue.use(VueRouter) //VueRouter 底 ...
- Pyppeteer入门(转载)
一.简介 Puppeteer 是 Google 基于 Node.js 开发的一个工具,有了它我们可以通过 JavaScript 来控制 Chrome 浏览器的一些操作,当然也可以用作网络爬虫上,其 A ...