题意:n个点, 坐标已知,其中横坐标为为1~n。 求区间[l, r] 的所有子区间内斜率最大值的和。
首先要知道,[l, r]区间内最大的斜率必然是相邻的两个点构成的。
然后问题就变成了求区间[l, r]内所有子区间最大值的和。
这个问题可以利用单调栈来做。
每次找到当前点左面第一个大于当前值的点, 然后更新答案。 姿势很多。
1 import java.io.BufferedInputStream; 2 import java.io.BufferedOutputStream; 3 import java.io.PrintWriter; 4 import java.util.Scanner; 5 6 7 8 public class Main { 9 static Scanner cin = new Scanner(new BufferedInputStream(System.in)); 10 static PrintWriter cout = new PrintWriter(new BufferedOutputStream(System.out)); 11 static final int maxn = 100005; 12 public static void main(String[] args) { 13 int []height = new int[maxn]; 14 while (cin.hasNext()){ 15 int n = cin.nextInt(); 16 int q = cin.nextInt(); 17 height[0] = 0; 18 for (int i = 1; i <= n; i++){ 19 height[i] = cin.nextInt(); 20 height[i-1] = Math.abs(height[i]-height[i-1]); 21 } 22 int []stack = new int[maxn]; 23 int top = -1; 24 for (int i = 0; i < q; i++){ 25 int l = cin.nextInt(); 26 int r = cin.nextInt(); 27 long res = 0, cur = 0; 28 top = -1; 29 for (int j = l; j < r; j++){ 30 while (top >= 0 && height[stack[top]] <= height[j]){ 31 cur -= 1L * height[stack[top]] * (stack[top] - (top==0 ? l-1 : stack[top-1])); 32 top--; 33 } 34 if (top >= 0){ 35 cur += 1L* (j - stack[top]) * height[j]; 36 }else{ 37 cur += 1L * (j - l + 1) * height[j]; 38 } 39 stack[++top] = j; 40 res += cur; 41 } 42 43 cout.println(res); 44 } 45 cout.flush(); 46 } 47 } 48 49 }
时间: 2024-10-06 06:39:01