我们定义一个有效序列为: 该序列两端的数一个为最小值,另一个为次小值。(即序列两端以外的数一定大于等于 最左边的数且大于等于 最右边的数) 现在给你一个序列 a ,想让你找到它的连续子序列中有多少个有效序列(比如 ,1 2 ,2 3,1 2 3 是序列 1 2 3 的连续子序列,但是 1 3 不是) 注:长度为 2 的子序列,一定为有效序列,长度为 1 的子序列,一定不是有效序列
区块链毕设网qklbishe.com为您提供问题的解答
我们定义一个有效序列为:该序列两端的数一个为最小值,另一个为次小值。(即序列两端以外的数一定大于等于最左边的数且大于等于最右边的数)
单调栈
正序遍历
arr:[1,1,2,1]
stack:[]
i=0,考察以arr[0]结尾,且以arr[0]为最小值的有效序列数,由于arr[0]的左边没有元素,所以直接入栈(为了考虑重复数字,需要记录某个数字的重复次数)
stack:[node(val=1,times=1)]
i=1,考察以arr[1]结尾,且以arr[1]为最小值的有效序列数,由于arr[0]=stack.top.val,直接压栈(与栈顶元素相同,增加栈顶元素的出现次数)
stack:[node(val=1,times=2)]
i=2,考察以arr[2]结尾,且以arr[2]为最小值的有效序列数,由于arr[2]>stack.top.val,直接压栈
stack:[node(val=1,times=2),node(val=2,times=1)]
i=3,考察以arr[3]结尾,且以arr[3]为最小值的有效序列数,而此时arr[3]<stack.top.val,破坏单调性,开始弹栈,栈顶元素为2,且只有一个2,说明可以与arr[3]构成一个有效的序列[2,1](刚好是以arr[3]结尾,且arr[3]为最小值,2为次小值)。
弹栈之后发现栈顶为1,且1出现了两次,可以与arr[3]构成两个有效序列,一个是①:[1,2,1],另一个是②:[1,1,2,1]。①中左边的1是把栈顶的2弹出后的次大值(由于栈是大压小的单调性,所以弹出2之后,如果栈顶元素仍然不小于arr[3],则栈顶元素一定可以作为次小值);同理②弹出的1也可以作为次小值。而两个1是同时弹出的,所以直接累加上2就可以了,此时已经有了[2,1],[1,2,1],[1,1,2,1]三个有效序列。
倒序遍历
import java.io.*; import java.util.*; class Node { public int value; public int times; public Node(int v, int t) { value = v; times = t; } } public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); if(n < 2){ System.out.println(0); return; } String[] strs = br.readLine().split(" "); int[] arr = new int[n]; for(int i = 0; i < n; i++){ arr[i] = Integer.parseInt(strs[i]); } long ans = 0; Stack<Node> stack = new Stack<>(); for(int i = 0; i < n; i++){ while(!stack.isEmpty() && stack.peek().value > arr[i]){ Node topNode = stack.pop(); ans += topNode.times + cn2(topNode.times); } if(!stack.isEmpty() && arr[i] == stack.peek().value){ stack.peek().times++; }else{ stack.push(new Node(arr[i], 1)); } } while(!stack.isEmpty()){ ans += cn2(stack.pop().times); } for(int i = n - 1; i >= 0; i--){ while(!stack.isEmpty() && stack.peek().value > arr[i]){ Node topNode = stack.pop(); ans += topNode.times; } if(!stack.isEmpty() && arr[i] == stack.peek().value){ stack.peek().times++; }else{ stack.push(new Node(arr[i], 1)); } } System.out.println(ans); } private static long cn2(int n) { return (long)n*(n - 1) >> 1; } }
复杂度分析
以上就是关于问题我们定义一个有效序列为: 该序列两端的数一个为最小值,另一个为次小值。(即序列两端以外的数一定大于等于 最左边的数且大于等于 最右边的数)
现在给你一个序列 a ,想让你找到它的连续子序列中有多少个有效序列(比如 ,1 2 ,2 3,1 2 3 是序列 1 2 3 的连续子序列,但是 1 3 不是)
注:长度为 2 的子序列,一定为有效序列,长度为 1 的子序列,一定不是有效序列的答案
欢迎关注区块链毕设网-
专业区块链毕业设计成品源码,定制。
区块链NFT链游项目方科学家脚本开发培训
从业7年-专注一级市场
微信:btc9767
TELEGRAM :https://t.me/btcok9
具体资料介绍
web3的一级市场千万收益的逻辑
进群点我
qklbishe.com区块链毕设代做网专注|以太坊fabric-计算机|java|毕业设计|代做平台-javagopython毕设 » 我们定义一个有效序列为: 该序列两端的数一个为最小值,另一个为次小值。(即序列两端以外的数一定大于等于 最左边的数且大于等于 最右边的数)
现在给你一个序列 a ,想让你找到它的连续子序列中有多少个有效序列(比如 ,1 2 ,2 3,1 2 3 是序列 1 2 3 的连续子序列,但是 1 3 不是)
注:长度为 2 的子序列,一定为有效序列,长度为 1 的子序列,一定不是有效序列
微信:btc9767
TELEGRAM :https://t.me/btcok9
具体资料介绍
web3的一级市场千万收益的逻辑
进群点我
qklbishe.com区块链毕设代做网专注|以太坊fabric-计算机|java|毕业设计|代做平台-javagopython毕设 » 我们定义一个有效序列为: 该序列两端的数一个为最小值,另一个为次小值。(即序列两端以外的数一定大于等于 最左边的数且大于等于 最右边的数)
现在给你一个序列 a ,想让你找到它的连续子序列中有多少个有效序列(比如 ,1 2 ,2 3,1 2 3 是序列 1 2 3 的连续子序列,但是 1 3 不是)
注:长度为 2 的子序列,一定为有效序列,长度为 1 的子序列,一定不是有效序列
进群点我
qklbishe.com区块链毕设代做网专注|以太坊fabric-计算机|java|毕业设计|代做平台-javagopython毕设 » 我们定义一个有效序列为: 该序列两端的数一个为最小值,另一个为次小值。(即序列两端以外的数一定大于等于 最左边的数且大于等于 最右边的数)
现在给你一个序列 a ,想让你找到它的连续子序列中有多少个有效序列(比如 ,1 2 ,2 3,1 2 3 是序列 1 2 3 的连续子序列,但是 1 3 不是)
注:长度为 2 的子序列,一定为有效序列,长度为 1 的子序列,一定不是有效序列
qklbishe.com区块链毕设代做网专注|以太坊fabric-计算机|java|毕业设计|代做平台-javagopython毕设 » 我们定义一个有效序列为: 该序列两端的数一个为最小值,另一个为次小值。(即序列两端以外的数一定大于等于 最左边的数且大于等于 最右边的数) 现在给你一个序列 a ,想让你找到它的连续子序列中有多少个有效序列(比如 ,1 2 ,2 3,1 2 3 是序列 1 2 3 的连续子序列,但是 1 3 不是) 注:长度为 2 的子序列,一定为有效序列,长度为 1 的子序列,一定不是有效序列