蓝桥杯 算法训练 操作格子 (最基本的线段树)
2014-02-26 21:39
267 查看
某渣终于开始写了第一次线段树了,哇咔咔!!!!!!!!!
题目:
算法训练 操作格子
时间限制:1.0s 内存限制:256.0MB
锦囊1
锦囊2
锦囊3
问题描述
有n个格子,从左到右放成一排,编号为1-n。
共有m次操作,有3种操作类型:
1.修改一个格子的权值,
2.求连续一段格子权值和,
3.求连续一段格子的最大值。
对于每个2、3操作输出你所求出的结果。
输入格式
第一行2个整数n,m。
接下来一行n个整数表示n个格子的初始权值。
接下来m行,每行3个整数p,x,y,p表示操作类型,p=1时表示修改格子x的权值为y,p=2时表示求区间[x,y]内格子权值和,p=3时表示求区间[x,y]内格子最大的权值。
输出格式
有若干行,行数等于p=2或3的操作总数。
每行1个整数,对应了每个p=2或3操作的结果。
样例输入
4 3
1 2 3 4
2 1 3
1 4 3
3 1 4
样例输出
6
3
数据规模与约定
对于20%的数据n <= 100,m <= 200。
对于50%的数据n <= 5000,m <= 5000。
对于100%的数据1 <= n <= 100000,m <= 100000,0 <= 格子权值 <= 10000。
明显的最基本的线段树
随便说一下某渣是看了两篇这题的题解才会做的:
/article/1468453.html
/article/1338285.html
还有HH大神写的一篇线段树完全版的解析
http://www.notonlysuccess.com/index.php/segment-tree-complete/
代码:
题目:
算法训练 操作格子
时间限制:1.0s 内存限制:256.0MB
锦囊1
锦囊2
锦囊3
问题描述
有n个格子,从左到右放成一排,编号为1-n。
共有m次操作,有3种操作类型:
1.修改一个格子的权值,
2.求连续一段格子权值和,
3.求连续一段格子的最大值。
对于每个2、3操作输出你所求出的结果。
输入格式
第一行2个整数n,m。
接下来一行n个整数表示n个格子的初始权值。
接下来m行,每行3个整数p,x,y,p表示操作类型,p=1时表示修改格子x的权值为y,p=2时表示求区间[x,y]内格子权值和,p=3时表示求区间[x,y]内格子最大的权值。
输出格式
有若干行,行数等于p=2或3的操作总数。
每行1个整数,对应了每个p=2或3操作的结果。
样例输入
4 3
1 2 3 4
2 1 3
1 4 3
3 1 4
样例输出
6
3
数据规模与约定
对于20%的数据n <= 100,m <= 200。
对于50%的数据n <= 5000,m <= 5000。
对于100%的数据1 <= n <= 100000,m <= 100000,0 <= 格子权值 <= 10000。
明显的最基本的线段树
随便说一下某渣是看了两篇这题的题解才会做的:
/article/1468453.html
/article/1338285.html
还有HH大神写的一篇线段树完全版的解析
http://www.notonlysuccess.com/index.php/segment-tree-complete/
代码:
#include<stdio.h> #include<math.h> #include<string.h> #include<algorithm> #include<limits.h> using namespace std; struct node { int l, r; int sum, max; }a[400001]; int Max(int x,int y) { return x> y? x: y; } void Build(int l,int r, int n)// 构建一颗范围为L-R的线段树 { a .l= l; a .r= r; a . sum= 0; a . max= 0; if(l==r) return; Build(l , (l + r) /2 , 2*n);// 构建该结点左子树[1,(l+r)/2] Build(1+(l+r) /2 , r, 2*n + 1);// 构建该结点右子树[1+(l+r)/2,r] } void Change(int n, int v, int num) //改变结点[v,v]的值 { if(v == a .l && v== a .r) { a .sum= num; a .max= num; return; } int mid= (a .l + a .r) / 2; if(v <= mid) Change(2*n, v, num);// 说明结点[V,V]在第n个结点的左子树上 else Change(1+ 2*n, v, num);// 说明结点[V,V]在第n个结点的右子树上 a .sum= a[2*n].sum + a[ 1+2*n ].sum; //从下往上更新所有父亲结点的值 a .max= Max(a[2*n].max,a[ 1+2*n ].max);//从下往上更新所有父亲结点的值 } int Qsum(int l, int r, int n) //求[l,r]之间权值的和 { if(l == a .l && r == a .r) return a .sum;// 说明第n结点刚好为[l,r]; int mid= (a .l + a .r)/2; //printf("%d\n",mid); if(r<= mid) return Qsum(l,r,2*n); //情况一:[l,r]全在第n个结点的左子树上 else if(l> mid) return Qsum(l,r,1+2*n); // 情况二: [l,r]全在第n个结点的右子树上 else return Qsum(l,mid,2*n) + Qsum(mid+1,r,1+2*n); //情况三:左右子树都占有 } int Qmax(int l, int r, int n)//求[l,r]之间的最大权值 { if(l == a .l && r == a .r) return a .max; int mid= ( a .l + a .r) /2; if(r<= mid) return Qmax(l,r,2*n); else if(l> mid) return Qmax(l,r,1+2*n); else return Max(Qmax(l,mid,2*n), Qmax(mid+1,r,1+2*n)); } int main() { int n,m; scanf("%d%d",&n,&m); Build(1,n,1);// 先建一颗1-n的线段树 for(int i= 1; i<= n; i++) { int t; scanf("%d",&t); Change(1,i,t); } while(m--) { int x,y,p; scanf("%d%d%d",&p,&x,&y); if(p == 1) Change(1,x,y); else if(p==2) { int sum= Qsum(x,y,1); printf("%d\n",sum); } else { int max= Qmax(x,y,1); printf("%d\n",max); } } return 0; }
相关文章推荐
- 蓝桥杯 算法训练 操作格子(线段树)
- 蓝桥杯 算法训练 操作格子 [ 线段树 ]
- [蓝桥杯]算法训练 操作格子-链式线段树
- 蓝桥杯 算法训练 操作格子 (线段树模板)
- 蓝桥杯算法训练_格子操作_线段树_区间和与区间最值
- 蓝桥杯 算法训练 操作格子 (线段树)
- 蓝桥杯算法训练——操作格子(线段树+单点更新+区间求和+求最大值)
- 蓝桥杯 ALGO-8 算法训练 操作格子(线段树)
- 蓝桥杯 算法训练 操作格子(线段树,点更新)
- 蓝桥杯-算法训练 操作格子
- 算法训练 操作格子 (线段树)
- 蓝桥杯 算法训练 操作格子
- 蓝桥杯_ 算法训练 操作格子
- 算法-蓝桥杯-算法训练 操作格子(C++)
- 算法训练 操作格子 线段树 单点修改,求区间和,区间最大值
- 蓝桥杯 算法训练 操作格子
- 算法训练 操作格子 线段树板子题
- 蓝桥杯 算法训练 操作格子 JAVA
- 算法训练 操作格子 线段树
- 蓝桥杯 算法训练 操作格子