链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1166

自己第一次在没有看题解AC出来的线段树,写的可能不是太好,再贴个学长的代码,学习一下

发现自己的Update部分写了很多废话,直接用a[r]里的值就好了,我还传了那么多的值,真傻!

代码:

 #include<stdio.h>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
using namespace std; #define Lson r<<1
#define Rson r<<1|1 const int N = 1e6+; struct SegmentTree
{
int L, R;
int sum, e;
int Mid()
{
return (R+L)>>;
}
}a[N<<]; void BuildSegTree(int r, int L, int R)
{
a[r].L=L, a[r].R=R;
a[r].e=; if(L==R)
{
scanf("%d", &a[r].sum);
return ;
} BuildSegTree(Lson, L, a[r].Mid());
BuildSegTree(Rson, a[r].Mid()+, R); a[r].sum = a[Lson].sum + a[Rson].sum;
} void Update(int r, int L, int R, int i, int e)
{
a[r].sum += e; if(L==R && L==i)
return ; if(i<=a[r].Mid())
Update(Lson, L, a[r].Mid(), i, e);
else if(i>a[r].Mid())
Update(Rson, a[r].Mid()+, R, i, e);
} int Query(int r, int L, int R)
{
if(a[r].L==L && a[r].R==R)
return a[r].sum; if(R<=a[r].Mid())
return Query(Lson, L, R);
else if(L>a[r].Mid())
return Query(Rson, L, R);
else
{
long long Lsum = Query(Lson, L, a[r].Mid());
long long Rsum = Query(Rson, a[r].Mid()+, R); return Lsum + Rsum;
}
} int main()
{
int t, k=;
scanf("%d", &t);
while(t--)
{
int n;
scanf("%d", &n);
BuildSegTree(, , n); char s[];
int L, R, i, e; printf("Case %d:\n", k++); while(scanf("%s", s), strcmp(s, "End"))
{
if(strcmp(s, "Query")==)
{
scanf("%d%d", &L, &R);
printf("%d\n", Query(, L, R));
}
else if(strcmp(s, "Add")==)
{
scanf("%d%d", &i, &e);
Update(, , n, i, e);
}
else
{
scanf("%d%d", &i, &e);
Update(, , n, i, -e);
}
}
}
return ;
}

学长的代码:

 #include<stdio.h>
#include<math.h>
#include<string.h> #define maxn 50005 struct node
{
int L, R, sum;//左右子树,sum记录区间和
int Mid(){return (L+R)/;}
}tree[maxn*];//为了保险起见一般定义是四倍
int val[maxn];//保存每个阵地原来的人数 void Build(int root, int L, int R)//建树
{
tree[root].L = L, tree[root].R = R; if(L == R)
{
tree[root].sum = val[L];
return ;
} Build(root<<, L, tree[root].Mid());//<<1 运算符相当于乘上 2,因为是数往左移一位
Build(root<<|, tree[root].Mid()+, R);//|1, 因为左移后最后一位是0, 所以与1进行|相当于+1 tree[root].sum = tree[root<<].sum+tree[root<<|].sum;//区间和等于左右区间的和
}
//k表示需要更新的点,e表示需要更新的值
void Insert(int root, int k, int e)
{
tree[root].sum += e;
if(tree[root].L == tree[root].R)
return ; if(k <= tree[root].Mid())
Insert(root<<, k, e);
else
Insert(root<<|, k, e);
}
//查询区间LR的和
int Query(int root, int L, int R)
{
if(tree[root].L == L && tree[root].R == R)
return tree[root].sum; //如果在左子树区间
if(R <= tree[root].Mid())
return Query(root<<, L, R);
else if(L > tree[root].Mid())//如果在右子树区间
return Query(root<<|, L, R);
else
{//在左右子树
int Lsum = Query(root<<, L, tree[root].Mid());
int Rsum = Query(root<<|, tree[root].Mid()+, R); return Lsum + Rsum;
}
} int main()
{
int T, t=; scanf("%d", &T); while(T--)
{
int i, N, x, y; scanf("%d", &N); for(i=; i<=N; i++)
scanf("%d", &val[i]);
Build(, , N); char s[]; printf("Case %d:\n", t++); while(scanf("%s", s), s[] != 'E')
{
scanf("%d%d", &x, &y); if(s[] == 'A')
Insert(, x, y);
else if(s[] == 'S')
Insert(, x, -y);
else
{
int ans = Query(, x, y);
printf("%d\n", ans);
}
}
} return ;
}

最新文章

  1. 解决Excel 2010只有一个窗口的问题
  2. Linux学习(一):从图形界面进入命令行及命令行进入图形界面
  3. CSS浏览器兼容问题总结
  4. CF 672C Recycling Bottles[最优次优 贪心]
  5. zepto源码--init--学习笔记
  6. node express 学习1
  7. JS实现漂亮的窗口拖拽效果(可改变大小、最大化、最小化、关闭)
  8. Softmax 回归原理介绍
  9. 转载 在.net中使用GAC
  10. 2016 ASC 移动物联网安全高峰论坛 万物互联时代的安全与隐私
  11. tr069开源协议EasyCwmp移植
  12. scrapy 命令行基本用法
  13. Linux Collection:文本编辑问题
  14. Ymodem协议(参考STM32)
  15. 安全测试5_服务端的安全漏洞(SQL注入、命令注入、文件操作类)
  16. ScrollView中嵌套GridView,Listview的办法
  17. linux线程学习
  18. C++构造函数和析构函数什么情况下会用
  19. configure: error: newly created file is older than distributed files!
  20. iOS彩票项目--第四天,新特性界面搭建,UICollectionViewController的初次使用

热门文章

  1. Jquery和Ajax
  2. How to Pronounce INTERNATIONAL
  3. C# 窗口页面卡的处理方案-异步编程委托
  4. ubuntu安装openssh-server 报依赖错误的解决过程
  5. 类的&quot;魔法&quot;方法
  6. Android通过DeepLink方式跳转其他App传递参数
  7. 修改hosts,***
  8. java非常好用的读取文件的流的代码
  9. 基于AspectJ的XML方式进行AOP开发
  10. 【校招面试 之 C/C++】第20题 C++ STL(二)之Vector