一、题目

  Sticks Problem

二、分析

  对于$i$和$j$,并没有很好的方法能同时将他们两找到最优值,所以考虑固定左端点$i$。

  固定左端点后,根据题意,$a[i]$是最小值,那么现在的问题就转化成了求以$a[i]$为左端点最小值的范围内,找到一个最大值$a[j]$的$j$,然后相减就是以$i$为左端点的最优值。

  然后枚举$i$,找到最大的$j-i$即可。

  如何找$j$,预先用ST表预处理好最大值最小值,然后先找以$i$为最小值的管辖范围(二分找,因为如果当前位置$pos$如果不满足,那么$j$肯定在$pos$的左边,反之可能在右边),再用ST表在这个范围内找到最大的$j$即可。

三、AC代码

 1 #include <cstdio>
2 #include <cstring>
3 #include <iostream>
4 #include <algorithm>
5 #include <vector>
6 #include <cmath>
7
8 using namespace std;
9 #define ll long long
10 #define Min(a,b) ((a)>(b)?(b):(a))
11 #define Max(a,b) ((a)>(b)?(a):(b))
12 const int MAXN = 5e4 + 13;
13 int N, a[MAXN], STmax[MAXN][30], STmin[MAXN][30];
14 int Logn[MAXN];
15
16 void pre_log()
17 {
18 Logn[1] = 0, Logn[2] = 1;
19 for(int i = 3; i <= MAXN; i++) {
20 Logn[i] = Logn[i/2] + 1;
21 }
22 }
23
24 void pre_st()
25 {
26 for(int i = 1; i <= N; i++) STmax[i][0] = i, STmin[i][0] = i;
27 int k = Logn[N];
28 for(int j = 1; j <= k; j++) {
29 for(int i = 1; i + (1<<j) - 1 <= N; i++) {
30 if(a[STmin[i][j-1]] < a[STmin[i+(1<<(j-1))][j-1]]) STmin[i][j] = STmin[i][j-1];
31 else STmin[i][j] = STmin[i+(1<<(j-1))][j-1];
32 if(a[STmax[i][j-1]] > a[STmax[i+(1<<(j-1))][j-1]]) STmax[i][j] = STmax[i][j-1];
33 else STmax[i][j] = STmax[i+(1<<(j-1))][j-1];
34 }
35 }
36 }
37
38 int query_min(int l, int r)
39 {
40 // int k = log(1.0*(r - l + 1))/log(2.0);
41 int k = Logn[r - l + 1];
42 if(a[STmin[l][k]] > a[STmin[r-(1<<k)+1][k]]) return STmin[r-(1<<k)+1][k];
43 else return STmin[l][k];
44 }
45
46 int query_max(int l, int r)
47 {
48 int k = log(1.0*(r - l + 1))/log(2.0);
49 if(a[STmax[l][k]] < a[STmax[r-(1<<k)+1][k]]) return STmax[r-(1<<k)+1][k];
50 else return STmax[l][k];
51 }
52
53 int query(int l, int r)
54 {
55 int p = l;
56 while(l < r) {
57 int mid = (l+r+1)>>1;
58 if(query_min(p, mid) == p) l = mid;
59 else r = mid-1;
60 }
61 return l;
62 }
63
64 int main()
65 {
66 pre_log();
67 while(scanf("%d", &N) != EOF) {
68 for(int i = 1; i <= N; i++) {
69 scanf("%d", &a[i]);
70 }
71 pre_st();
72 int ans = -1;
73 for(int i = 1; i < N; i++) {
74 //先以i为最小值进行查找最大的管辖范围
75 //再求范围内的最大j
76 int j = query_max(i, query(i, N));
77 if(j - i == 0)
78 continue;
79 else
80 ans = Max(ans, j - i);
81 }
82 printf("%d\n", ans);
83 }
84 return 0;
85 }

最新文章

  1. About_PHP_验证码的生成
  2. EPSON LQ610K 设置税控盘打印发票的格式
  3. AngularJS入门心得2——何为双向数据绑定
  4. zabbix-agent passive
  5. 使用CollectionView做横向滑动分页效果:
  6. python遍历文件夹下的文件
  7. 文件上传工具类 UploadUtil.java
  8. Sql Xtype
  9. Ext.net.DirectMethods
  10. 编译器报错:&#39;IHTMLControlElement&#39; : redefinition
  11. J2EE走向成功路-02-Struts2 配置(Maven)
  12. Python Day2 (二)
  13. bytes,bytearray
  14. Python学习周末练习1-用户登录
  15. Windows驱动匹配详解
  16. SLAM数据集整理
  17. Excel函数(不定期持续更新)
  18. Huffman Implementation with Python
  19. oracle12c的日志查看
  20. CodeSign error: code signing is required for product type Application in SDK iOS XXX的解决办法

热门文章

  1. 查找命令中grep,find,which和whereis的使用及区别
  2. kmp--考研写法
  3. Android 神奇的SpannableStringBuilder
  4. SwiftUI error All In One
  5. self-publishing ebook guide all in one
  6. CSS border gradient color All In One
  7. JavaScript Weekly
  8. apollo-server 返回模拟数据
  9. Flutter: MobX和flutter_mobx状态管理器
  10. 我眼中的价值币——NGK(下)