题目链接:http://codeforces.com/problemset/problem/602/B
题意:
给你一个相邻数差不超过 1 的序列,求最长子串的长度,满足子串中的最大值减最小值也不超过 1。
思路:
区间最大值,区间最小值分别用ST表去维护就可以了,然后之后去二分答案就好了
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <math.h> 6 #include <set> 7 #include <vector> 8 #include <stack> 9 10 using namespace std; 11 const int maxn= 1e5 + 10; 12 13 int n; 14 int arr[maxn]; 15 int dp[maxn][100]; 16 int dp1[maxn][100]; 17 18 int Min(int l,int r){ 19 int k = log(r-l+1)/log(2); 20 return min(dp[l][k],dp[r-(1<<k)+1][k]); 21 } 22 23 int Max(int l,int r){ 24 int k = log(r-l+1)/log(2); 25 return max(dp1[l][k],dp1[r-(1<<k)+1][k]); 26 } 27 28 bool check(int x){ 29 for (int i=1;i+x-1<=n;i++){ 30 if (Max(i,i+x-1)-Min(i,i+x-1)<=1) 31 return true; 32 } 33 return false; 34 } 35 36 int main(){ 37 scanf("%d",&n); 38 for (int i=1;i<=n;i++){ 39 scanf("%d",&arr[i]); 40 } 41 for (int i=1;i<=n;i++){ 42 dp[i][0] = arr[i]; 43 dp1[i][0] = arr[i]; 44 } 45 for (int j=1;(1<<j)<=n;j++){ 46 for (int i=1;i+(1<<j)-1<=n;i++){ 47 dp[i][j] = min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); 48 dp1[i][j] = max(dp1[i][j-1],dp1[i+(1<<(j-1))][j-1]); 49 } 50 } 51 int l=1,r=n+1,mid; 52 int len = 1; 53 while (l<=r){ 54 mid = (l+r)/2; 55 if (check(mid)){ 56 len = max(mid,len); 57 l = mid + 1; 58 } 59 else{ 60 r = mid-1; 61 } 62 } 63 printf("%d ",len); 64 return 0; 65 }