HDU - 1556 和1166,线段树的区间插入,单点查找和单点插入与区间查找
来源:互联网 发布:php各大视频解析源码 编辑:程序博客网 时间:2024/04/29 23:02
今天对最近几天学的线段树来总结一下。线段树解决的问题就是对查询的过程加快。
1.区间插入,单点查询。
HDU - 1556
#include <iostream>#include <cstdio>#define maxn 100005using namespace std;struct node{ int l,r,v;//l,r在这里代表的是左边的值和右边的值,v在这里维护的是被涂色的次数};node d[maxn<<2];void buildtree(int i,int l,int r)//建树{ d[i].l=l,d[i].r=r,d[i].v=0; if(d[i].l==d[i].r) return; int mid=(d[i].l+d[i].r)/2; buildtree(i<<1,l,mid);//位运算符,表示i*2 buildtree(i<<1|1,mid+1,r);//表示i*2+1}void Insert(int i,int a,int b)//因为是区间插入,然后找到一个区间{ if(d[i].l==a&&d[i].r==b)//找到了一个区间,为什么在这个区间++,那下面的具体的点呢?(答案在下面) { d[i].v++; return; } int mid=(d[i].l+d[i].r)/2; if(b<=mid) Insert(i<<1,a,b); else if(a>=mid+1) Insert(i<<1|1,a,b); else { Insert(i<<1,a,mid); Insert(i<<1|1,mid+1,b); }}int Count(int i,int a)//查询,单点查询{ if(d[i].l==d[i].r)//单点查询,所以是到某个具体的点 { return d[i].v; } int mid=(d[i].l+d[i].r)/2; if(a<=mid) return Count(i<<1,a)+d[i].v;//这里还是要加return的,如果函数返回类型是int的话,就是要返回值,不然的话,就会返回一些奇怪的东西。如果返回类型是void的话,递归的话,可以加return也可以不用。然后return是之间当前操作结束,所以如果后面要加其他操作的,就要注意下了。 else if(a>mid) return Count(i<<1|1,a)+d[i].v;//红色部分,这里也是一个小技巧,就是之前在某个区间v作为下面每个的次数的话,我们就可以在查询的时候加int main(){ int n; while(scanf("%d",&n)!=EOF) { if(n==0) break; buildtree(1,1,n); for(int i=0;i<n;i++) { int a,b; scanf("%d %d",&a,&b); Insert(1,a,b); } for(int i=1;i<n;i++) printf("%d ",Count(1,i)); printf("%d\n",Count(1,n)); } return 0;}
2单点插入,区间和查询
题目 Hdu 1166 https://vjudge.net/problem/16216/origin
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define maxn 50005struct node{ int l,r,v;//因为查询的是区间和,所以V维护的是区间和};node d[maxn<<2];void buildtree(int i,int l,int r){ d[i].l=l,d[i].r=r; if(l==r) { scanf("%d",&d[i].v);//这个是直接到了那个点的时候输入 return ; } int mid=(d[i].l+d[i].r)/2; buildtree(i<<1,l,mid); buildtree(i<<1|1,mid+1,r); d[i].v=d[i<<1].v+d[i<<1|1].v;//相当于向上维护,注意这里是可以的,但是如果前面是 return buildtree()的时候就不行了,这一步就不会执行}void Insert(int i,int a,int v){ if(d[i].l==d[i].r) { d[i].v+=v; return ; } int mid=(d[i].l+d[i].r)/2; if(a<=mid) Insert(i<<1,a,v); if (a>=mid+1) Insert(i<<1|1,a,v); d[i].v=d[i<<1].v+d[i<<1|1].v;//插入之后,新增的会影响原来的,所以也要维护。}char q[10];int Count(int i,int l,int r){ if(d[i].l==l&&d[i].r==r) return d[i].v; int mid=(d[i].l+d[i].r)/2; if(r<=mid) return Count(i<<1,l,r); else if(l>=mid+1) return Count(i<<1|1,l,r); else return Count(i<<1,l,mid)+Count(i<<1|1,mid+1,r);//这个是在中间的情况}int main(){ int T,n; scanf("%d",&T); int temp=T; while(T--) { memset(d,0,sizeof(d)); scanf("%d",&n); buildtree(1,1,n); int ans=0; printf("Case %d:\n",temp-T); while(scanf("%s",q)&&q[0]!='E') { int a,b; scanf("%d %d",&a,&b); if(q[0]=='A') Insert(1,a,b); if(q[0]=='S') Insert(1,a,-b); if(q[0]=='Q') { printf("%d\n",Count(1,a,b)); } } } return 0;}
据说以上问题可以用树状数组来做,可是我还没开始学树状数组,下次学了之后用树状数组再来写一遍。
0 0
- HDU - 1556 和1166,线段树的区间插入,单点查找和单点插入与区间查找
- hdu 1166 线段树单点更新和区间求和
- HDU 1166(线段树,单点加减 询问区间和)
- 线段树求区间和(单点更新)
- 线段树单点更新和区间查询
- 线段树 单点更新求区间和
- poj 2828(线段树:单点插入,区间查询)
- 单点更新+区间求最值与和_线段树
- HDU 1166 线段树的单点更新 区间求和
- 线段树 的单点更新和区间求和
- [模板练习]线段树的单点修改和区间查询
- 线段树基础单点更新,区间查找HDU1166,POJ3264,DUT1094等差区间,HDU1754
- HDU 4819:单点更新,区间查询的二维线段树
- HDU 3308 LCIS 线段树的单点更新,区间合并
- 线段树 hdu 1166 敌兵布阵 单点更新区间求和
- HDU 1166 敌兵布阵 (线段树 单点增减, 区间求和)
- hdu 1166 敌兵布阵【线段树】单点更新,区间求和
- hdu 1166 线段树(单点更新,区间求和)
- mongodb3.X权限配置
- RTP协议全解析(H264码流和PS流)
- Java之——Hash算法大全
- 关于java web项目编写数据库连接的方法
- HDU3368-Reversi
- HDU - 1556 和1166,线段树的区间插入,单点查找和单点插入与区间查找
- H5使用canvas实现星星闪烁效果
- nginx下的.htaccess
- map集合一点小总结
- 【c++】准备阶段
- linux设备驱动归纳总结(一):内核的相关基础概念
- 图片加载小框架
- 沃美转眼来到广宇群山之巅
- Ubuntu系统安装