题目大意
给定一个长度为m的序列S,定义其特征值为
{
{
}}
选定的子序列长度必须至少为2,即j - i > 0.
数据范围
30%:
60%:
100%:
Solution
100%:
注意到随着区间长度的增长,m会变大,
{
}会变小.
设当前区间为[l..r],比较m和
{
},若m较小则把r + 1,否则l + 1.
使用multiset做到O(
)
Code
#include <cstdio>
#include <cmath>
#include <set>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 2e6 + 5;
const long long INF = 10000000000;
long long n,l = 1,r = 2,ans = 0x3f3f3f3f;
long long a[N];
multiset <long long>::iterator faq;
multiset <long long> val,dif;
long long Check()
{
return *(dif.begin());
}
void Add(long long x)
{
faq = val.insert(x);
long long t = *(++faq);faq--;long long t1 = *(--faq);faq++;
dif.erase(dif.find(abs(t - t1)));
dif.insert(abs(x - t));
dif.insert(abs(x - t1));
}
void Remove(long long x)
{
faq = val.find(x);
long long t = *(++faq);faq--;long long t1 = *(--faq);faq++;
dif.insert(abs(t - t1));
dif.erase(dif.find(abs(x - t)));
dif.erase(dif.find(abs(x - t1)));
val.erase(faq);
}
int main()
{
freopen("random.in","r",stdin);
freopen("random.out","w",stdout);
scanf("%lld",&n);
for (int i = 1 ; i <= n ; i++) scanf("%lld",&a[i]);
val.insert(-INF),val.insert(INF);
dif.insert(INF + INF);
Add(a[1]),Add(a[2]);
while (r <= n)
{
ans = min(ans,max(r - l + 1,Check()));
if (r - l + 1 < Check())
{
r++;
Add(a[r]);
}
else
{
Remove(a[l]);
l++;
}
}
printf("%lld\n",ans);
fclose(stdin);
fclose(stdout);
return 0;
}