题目链接:http://codeforces.com/problemset/problem/602/B
题意:找一个最长区间满足区间的最大值减最小值<=1
思路:。。。相邻两个数之差≤1很关键!!!!!!!!我特么傻傻的写了半天的尺取+线段树,如果相邻两个数之差≤1的话,那么前面最后出现的要么是x-1 要么是x+1 要么是x (假设当前数是x 并且只考虑x-1 x+1就对了,因为他们是可取到的边界) 如果最后出现的是x-1 那么就考虑x-2和x+1哪个最后出现,以此为边界, x+1的情况类似
AC代码(尺取法+线段树):
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
const int INF = 0x3f3f3f3f;
int a[MAXN];
long long minv[MAXN << 2], maxv[MAXN << 2], add[MAXN << 2];
void pushUp(int o) {
minv[o] = min(minv[o << 1], minv[o << 1 | 1]);
maxv[o] = max(maxv[o << 1], maxv[o << 1 | 1]);
}
void pushDown(int o, int lc, int rc) {
if (add[o] != -1) {
minv[o << 1] = min(minv[o << 1], add[o]);
minv[o << 1 | 1] = min(minv[o << 1 | 1], add[o]);
maxv[o << 1] = max(maxv[o << 1], add[o]);
maxv[o << 1 | 1] = max(maxv[o << 1 | 1], add[o]);
add[o << 1] = add[o];
add[o << 1 | 1] = add[o];
add[o] = -1;
}
}
void build(int o, int L, int R) {
if (L == R) {
minv[o] = a[L];
maxv[o] = a[L];
}
else {
int m = L + ((R - L) >> 1);
build(o << 1, L, m);
build(o << 1 | 1, m + 1, R);
pushUp(o);
}
}
void update(int o, int L, int R, int C, int l, int r) {
if (L >= l && R <= r) {
minv[o] = C;
maxv[o] = C;
add[o] = C;
}
else {
int m = L + ((R - L) >> 1);
pushDown(o, m - L + 1, R - m);
if (l <= m) {
update(o << 1, L, m, C, l, r);
}
if (r > m) {
update(o << 1 | 1, m + 1, R, C, l, r);
}
pushUp(o);
}
}
long long query1(int o, int L, int R, int l, int r) {
if (L >= l && R <= r) {
return minv[o];
}
else {
long long ans = INF;
int m = L + ((R - L) >> 1);
pushDown(o, m - L + 1, R - m);
if (l <= m) {
ans = min(ans, query1(o << 1, L, m, l, r));
}
if (r > m) {
ans = min(ans, query1(o << 1 | 1, m + 1, R, l, r));
}
return ans;
}
}
long long query2(int o, int L, int R, int l, int r) {
if (L >= l && R <= r) {
return maxv[o];
}
else {
long long ans = 0;
int m = L + ((R - L) >> 1);
pushDown(o, m - L + 1, R - m);
if (l <= m) {
ans = max(ans, query2(o << 1, L, m, l, r));
}
if (r > m) {
ans = max(ans, query2(o << 1 | 1, m + 1, R, l, r));
}
return ans;
}
}
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
memset(add, -1, sizeof(add));
build(1, 1, n);
int en = 1, st = 1, ans = 1;
while (st <= n) {
if (n - st + 1 <= ans) {
break;
}
while (1) {
if (query2(1, 1, n, st, en) - query1(1, 1, n, st, en) > 1) {
break;
}
en++;
if (en >= n + 1) {
break;
}
}
ans = max(ans, en - st);
st++;
}
printf("%d\n", ans);
return 0;
}
正确做法(代码摘自
gungnir__
博客):原文链接 http://blog.csdn.net/gungnir0711/article/details/50280247#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+50;
int a[maxn],dp[maxn];
int main()
{
int n;
scanf("%d",&n);
int ans=0;
for( int i=1; i<=n; i++ )
{
int x;
scanf( "%d",&x );
if( dp[x-1]>dp[x+1] ) ans=max( ans,i-max( dp[x-2],dp[x+1] ) );
else ans=max( ans, i-max(dp[x+2],dp[x-1] ) );
dp[x]=i;
}
printf( "%d\n",ans );
return 0;
}