蓝桥杯 算法训练 操作格子
2018-03-09 14:57
330 查看
问题描述
输入格式
输出格式
样例输入
4 3
1 2 3 4
2 1 3
1 4 3
3 1 4
样例输出
6
3
数据规模与约定
tips:
1.使用线段树。
2.线段树的每个结点记录下这一段区间所有数的和以及最大值即可。
根据提示,我们选用线段树做法,但是还是无法通过测试,原因还是运行超时。
思考:可能是因为我构造线段树,还是使用的数组,而且是2倍多的数组,答案太大。
贴出代码,希望有大佬可以帮我找到更好的方法,虽然未通过,可还是对线段树回溯还有递归构造有了一定的深度。
概念参考:数据结构专题——线段树
有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。
tips:
1.使用线段树。
2.线段树的每个结点记录下这一段区间所有数的和以及最大值即可。
根据提示,我们选用线段树做法,但是还是无法通过测试,原因还是运行超时。
思考:可能是因为我构造线段树,还是使用的数组,而且是2倍多的数组,答案太大。
贴出代码,希望有大佬可以帮我找到更好的方法,虽然未通过,可还是对线段树回溯还有递归构造有了一定的深度。
概念参考:数据结构专题——线段树
import java.util.Scanner; class TreeNode{ int max; int sum; } public class Main { //创建树,并且赋最小值 public static void buildTree(int[] arr,TreeNode[] segTree,int node,int begin,int end) { if(begin == end) { segTree[node].max = arr[begin];//只有一个元素,节点记录该单元素 segTree[node].sum = arr[begin]; }else { //递归构造左右子树 buildTree(arr,segTree,2 * node, begin ,(begin + end) / 2); buildTree(arr,segTree,2 * node + 1,(begin + end) / 2 + 1,end); //回溯时得到当前node结点的线段信(最大值) if(segTree[2 * node].max >= segTree[2 * node + 1].max) { segTree[node].max = segTree[2 * node].max; }else { segTree[node].max = segTree[2 * node + 1].max; } //回溯得到当前node结点的线段信息(和) segTree[node].sum = segTree[2 * node].sum + segTree[2 * node + 1].sum; } } //查询区间最大值 public static int queryMax(TreeNode[] segTree,int node,int begin,int end,int left,int right) { int p1,p2; //查询区间和要求的区间有没有交集 if(left > end || right < begin) { return -1; } if(begin >= left && end <= right) return segTree[node].max; p1 = queryMax(segTree,2 * node,begin,(begin + end) / 2,left,right); p2 = queryMax(segTree,2 * node + 1,(begin + end) / 2 + 1,end,left,right); // System.out.println(p1+" "+p2); if(p1 == -1) return p2; if(p2 == -1) return p1; if(p1 >= p2) return p1; return p2; } //查询区间最大值 public static int querySum(TreeNode[] segTree,int node,int begin,int end,int left,int right) { int p1,p2; //查询区间和要求的区间有没有交集 if(left > end || right < begin) { return -1; } if(begin >= left && end <= right) return segTree[node].sum; p1 = querySum(segTree,2 * node,begin,(begin + end) / 2,left,right); p2 = querySum(segTree,2 * node + 1,(begin + end) / 2 + 1,end,left,right); if(p1 == -1) return p2; if(p2 == -1) return p1; if(p1 != -1 && p2 != -1) return p1 + p2; return p2; } public static void choice1(int[] arr,TreeNode[] segTree,int i,int newNum) { arr[i] = newNum; buildTree(arr,segTree,1,0,arr.length - 1); } public static void main(String[] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); int[] arr = new int ; TreeNode[] segTree = new TreeNode[n * 4 + 10]; for(int i = 0;i < segTree.length;i++) { segTree[i] = new TreeNode(); } for(int i = 0;i < n;i ++) { arr[i] = sc.nextInt(); } buildTree(arr,segTree,1,0,n - 1); while(m > 0) { int choice = sc.nextInt(); if(choice == 1) { int i = sc.nextInt(); int newNum = sc.nextInt(); choice1(arr,segTree,i - 1,newNum); }else if(choice == 2) { int left = sc.nextInt(); int right = sc.nextInt(); System.out.println(querySum(segTree,1,0,n - 1,left - 1,right -1)); }else if(choice == 3) { int left = sc.nextInt(); int right = sc.nextInt(); System.out.println(queryMax(segTree,1,0,n - 1,left - 1,right - 1)); } m --; } } }
相关文章推荐
- 蓝桥杯算法训练_格子操作_线段树_区间和与区间最值
- 蓝桥杯_ 算法训练 操作格子
- [蓝桥杯]算法训练 操作格子-链式线段树
- 蓝桥杯-算法训练--ALGO-8 操作格子
- 蓝桥杯 算法训练 操作格子 (线段树模板)
- 蓝桥杯 算法训练 操作格子(线段树)
- 蓝桥杯_算法训练_操作格子
- 蓝桥杯算法训练——操作格子(线段树+单点更新+区间求和+求最大值)
- 蓝桥杯 算法训练 操作格子 (最基本的线段树)
- 蓝桥杯 算法训练 操作格子
- 蓝桥杯 算法训练 操作格子 [ 线段树 ]
- 蓝桥杯 算法训练 操作格子(线段树,点更新)
- 蓝桥杯 算法训练 操作格子 (线段树)
- 蓝桥杯 算法训练 操作格子
- 蓝桥杯 ALGO-8 算法训练 操作格子(线段树)
- 蓝桥杯 算法训练 操作格子 JAVA
- 蓝桥杯 算法训练 操作格子
- 蓝桥杯-算法训练 操作格子
- 算法-蓝桥杯-算法训练 操作格子(C++)
- 算法训练 操作格子