java实现 蓝桥杯 算法训练 操作格子
生活随笔
收集整理的這篇文章主要介紹了
java实现 蓝桥杯 算法训练 操作格子
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
問題描述
有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。
運行超時,一半的分數,還望java大佬解決 package com.liuzhen.systemExe;import java.util.Scanner;public class Main{public int[][] segTree;/** 參數root:代表線段樹的根節點,此處使用數組存放線段樹,其根節點從0開始計數,那么其兩個子節點編號必定滿足2*root+1或者2*root+2* 參數array:給定的目標數組,需要轉成相應功能的線段樹* 參數start:線段樹劃分給定數組區間的起始位置* 參數end:線段樹劃分給定數組區間的末尾位置* 函數功能:返回一個線段樹,其所有節點均存放當前數組子區間內的總和以及最大值*/public void buildSegTree(int root, int[] array, int start, int end) {if(start == end) {segTree[root][0] = array[start]; segTree[root][1] = array[start];} else {int mid = (start + end) / 2;buildSegTree(2 * root + 1, array, start, mid); //遞歸構造左半子樹buildSegTree(2 * root + 2, array, mid + 1, end); //遞歸構造右半子樹segTree[root][0] = (segTree[2*root+1][0] > segTree[2*root+2][0] ? segTree[2*root+1][0] : segTree[2*root+2][0]); //回溯求取當前節點區間存放的元素最大值segTree[root][1] = segTree[root*2+1][1] + segTree[root*2+2][1]; //回溯求取當前節點區間存放的元素總和}}/** 參數root:開始進行查找的根節點對應的數組下標值* 參數start-end:當前節點所表示的區間* 參數qstart-qend:此次查詢的區間* 函數功能:查詢當前區間qstart-qend的最大值*/public int querySegTreeMax(int root, int start, int end, int qstart, int qend) {if(qstart > end || qend < start)return 0;int max = 0;if(qstart <= start && qend >= end) {return segTree[root][0];} else {int mid = (start + end) / 2;int temp1 = querySegTreeMax(root * 2 + 1, start, mid, qstart, qend);int temp2 = querySegTreeMax(root * 2 + 2, mid + 1, end, qstart, qend);if(temp1 > temp2)max = temp1;elsemax = temp2;} return max;}/** 參數root:開始進行查找的根節點對應的數組下標值* 參數start-end:當前節點所表示的區間* 參數qstart-qend:此次查詢的區間* 函數功能:查詢當前區間qstart-qend的總和*/public int querySegTreeSum(int root, int start, int end, int qstart, int qend) {if(qstart > end || qend < start )return 0;int sum = 0;if(qstart == start && qend == end) {return segTree[root][1];} else {int mid = (start + end) / 2;if(qstart <= mid && qend > mid) {int temp1 = querySegTreeSum(root * 2 + 1, start, mid, qstart, mid);int temp2 = querySegTreeSum(root * 2 + 2, mid + 1, end, mid + 1, qend);sum = temp1 + temp2;} else if(qstart > mid) {int temp2 = querySegTreeSum(root * 2 + 2, mid + 1, end, qstart, qend);sum = temp2;} else if(qend <= mid) {int temp1 = querySegTreeSum(root * 2 + 1, start, mid, qstart, qend);sum = temp1;}}return sum;}/** 參數root:開始進行查找的根節點對應的數組下標值* 參數qstart-qend:當前節點所表示的區間* 函數功能:把數組下標為index的元素值變成value,并更新線段樹*/public void updateSegTree(int root, int qstart, int qend, int index, int value) {if(qstart == qend) {if(index == qstart) {segTree[root][0] = value;segTree[root][1] = value;}return;}int mid = (qstart + qend) / 2;if(mid >= index) {updateSegTree(root * 2 + 1, qstart, mid, index, value);} else {updateSegTree(root * 2 + 2, mid + 1, qend, index, value);}//回溯更新改變值元素值的根節點相應值segTree[root][0] = (segTree[root*2+1][0] > segTree[root*2+2][0] ? segTree[root*2+1][0] : segTree[root*2+2][0]);segTree[root][1] = segTree[root*2+1][1] + segTree[root*2+2][1];}public void printResult(int[] A, int[][] operation) {segTree = new int[4 * A.length][2];//此處初始化線段樹行的長度為4 * n,有n個元素的數組構造的線段樹其對應的二叉樹層數最大可以達到4*n個節點buildSegTree(0, A, 0, A.length - 1);for(int i = 0;i < operation.length;i++) {if(operation[i][0] == 1) {updateSegTree(0, 0, A.length - 1, operation[i][1] - 1, operation[i][2]);} else if(operation[i][0] == 2) {int sum = querySegTreeSum(0, 0, A.length - 1, operation[i][1] - 1, operation[i][2] - 1);System.out.println(sum);} else if(operation[i][0] == 3) {int max = querySegTreeMax(0, 0, A.length - 1, operation[i][1] - 1, operation[i][2] - 1);System.out.println(max);}}}public static void main(String[] args){Main test = new Main();Scanner in = new Scanner(System.in);int n = in.nextInt();int m = in.nextInt();if(n >100000 || n <= 0 || m > 100000 || m <= 0) //此處是依據題意給定范圍做判斷return;int[] A = new int[n];for(int i = 0;i < n;i++) A[i] = in.nextInt();int[][] operation = new int[m][3];for(int i = 0;i < m;i++) {for(int j = 0;j < 3;j++) {operation[i][j] = in.nextInt();}} test.printResult(A, operation); } }總結
以上是生活随笔為你收集整理的java实现 蓝桥杯 算法训练 操作格子的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大数据时代数据资产管理“五星模型”:三个
- 下一篇: 区块链中的分叉