线段树的模板(更新ing)
来源:互联网 发布:辩论赛网络的利与弊 编辑:程序博客网 时间:2024/06/06 13:06
1.单点修改(增加/减少)+区间求和
例题:计蒜客 斑点蛇(敌兵布阵)
第一行一个正整数 N(N≤50000)表示这条斑点蛇长度为 N 厘米,接下来有 N 个正整数,第i 个正整数 a_i
代表第 i 个斑点蛇第 i 厘米开始时有 a_i个斑点( 1≤ai≤50)。
接下来每行有一条命令,命令有4 种形式:
(1) Add i j,i 和 j 为正整数,表示第 i 厘米增加 j 个斑点(j 不超过 30);
(2) Sub i j,i 和 j 为正整数,表示第 i 厘米减少 j 个斑点(j 不超过 30);
(3) Query i j,i 和 j 为正整数,i≤j,表示询问第 i 到第 j 厘米的斑点总数(包括第 i 厘米和第 j 厘米);
(4) End 表示结束,这条命令在每组数据最后出现;
最多有 40000 条命令。
输出格式
对于每个 Query 询问,输出一个整数并回车,表示询问的段中的总斑点数,这个数保证在int范围内。
#include<bits/stdc++.h>using namespace std;int n,s[200004]={0},a[50001];void build(int num,int l,int r){ if(l==r) { s[num]=a[l]; return; } int mid=(l+r)/2; build(num*2,l,mid); build(num*2+1,mid+1,r); s[num]=s[num*2]+s[num*2+1];}void modify(int p,int l,int r,int x,int v){//吧父亲的信息传给儿子 s[p]+=v; if(l==r) return;//叶结点则退 出 int mid=(l+r)/2; if(x<=mid)//判断x在左儿子还是右儿子 modify(p*2,l,mid,x,v); else modify(p*2+1,mid+1,r,x,v);}int query(int p,int l,int r,int x,int y){ if(x<=l&&r<=y) return s[p];//若该结点被所查询区间包含 int mid=(l+r)/2; int res=0; if(x<=mid) res+=query(p*2,l,mid,x,y); if(y>mid) res+=query(p*2+1,mid+1,r,x,y); return res;}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); string s; for(;;){ cin>>s; if(s=="Add"){ int i,j; cin>>i>>j; modify(1,1,n,i,j); } else if(s=="Sub"){ int i,j; cin>>i>>j; modify(1,1,n,i,0-j); }else if(s=="Query"){ int i,j; cin>>i>>j; cout<<query(1,1,n,i,j)<<endl; } else if(s=="End"){ break; } } return 0;}
裸的套模板就行
写这题的时候才发现……计蒜客没讲怎么建树2333
2.单点覆盖+区间最值
习题:最甜的苹果
(I HATe it)
又找到原题了……
题目描述:很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。 这让很多学生很反感。 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。输入: 本题目包含多组测试,请处理到文件结束。 在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目。 学生ID编号分别从1编到N。 第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩。 接下来有M行。每一行有一个字符 C (只取'Q'或'U') ,和两个正整数A,B。 当C为'Q'的时候,表示这是一条询问操作,它询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少。 当C为'U'的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。 输出: 对于每一次询问操作,在一行里面输出最高成绩。 样例输入: 5 7 1 2 3 4 5 Q 1 5 U 3 6 Q 3 4 Q 4 5 U 2 9 Q 1 5 Q 2 4样例输出: 5 6 5 9 9 这次要建的是最值树,建树和查询,修改的子函数都要改用结构体储存最值(我为什么不直接用数组……)还有区间修改……慢慢补
#include<bits/stdc++.h>using namespace std;const int maxn=200001;struct tree{ int maxx=0;}s[maxn*4+10];int n,m;void build(int num,int l,int r){ if(l==r){ cin>>s[num].maxx; return; } int mid=(l+r)>>1; build(num*2,l,mid); build(num*2+1,mid+1,r); s[num].maxx=max(s[num*2].maxx,s[num*2+1].maxx);//最值建树}void modify(int p,int l,int r,int x,int v){ if(l==r&&l==x) {s[p].maxx=v;return;} //是叶结点则退出 int mid=(l+r)/2; if(x<=mid){//是在儿子还是女儿 modify(p*2,l,mid,x,v);//左 } else modify(p*2+1,mid+1,r,x,v); s[p].maxx=max(s[p*2].maxx,s[p*2+1].maxx);//更新父亲结点}int query(int p,int l,int r,int x,int y){ if(x<=l&&r<=y){ return s[p].maxx; } int mid=(l+r)/2,res=0; if(x<=mid) res=max(res,query(p*2,l,mid,x,y)); if(y>mid) res=max(res,query(p*2+1,mid+1,r,x,y)); return res;}int main(){ cin>>n>>m; build(1,1,n); char c; int x,y; while(m--){ cin>>c>>x>>y; if(c=='Q') { cout<<query(1,1,n,x,y)<<endl; }else if(c=='U'){ modify(1,1,n,x,y); } } return 0;}
阅读全文
0 0
- 线段树的模板(更新ing)
- Pein线段树总结(陆续更新ing)
- 线段树模板(区间更新)
- ACM_线段树模板(区间更新)
- [模板]线段树的建树、查询、单点更新、区间更新
- NYOJ 1185-最大最小值【线段树:模板--学习ing】
- 线段树成段更新的模板
- 线段树 区间更新模板
- 线段树单点更新模板
- 线段树(单点更新(模板)) 之 hdu 1166
- hdu1166 敌兵布阵(线段树点更新模板题)
- HDOJ 5217 Brackets(zkw线段树模板+单点更新)
- poj 3468 线段树区间更新(基础,模板)
- hdu 1166 线段树 点更新(孙启龙模板)
- Color the ball (线段树,区间更新模板题)
- HDU 4819 Mosaic(二维线段树单点更新+区间查询+自己的写法模板)
- HDU 1698 线段树区间更新模板
- 线段树区间更新&&HDU1698模板
- Bertown Subway CodeForces
- 工作5年,我的互联网工具箱(30个提升办公效率的神器)
- 设计模式之观察者模式
- 接口
- 关于多态
- 线段树的模板(更新ing)
- 数组类的分功能实现
- 在有序旋转数组中找到一个数
- scrapy爬虫框架入门实例
- (递归)十进制转换成二进制
- tcp/ip学习笔记--第9章 ip routing(选路)
- 并行和并发的区别
- Oracl之开窗函数
- Mybatis批量插入返回成功的数目