题目大意:给定n,k和一个长度为n的序列,求最长的最大值最小值相差不超过k的序列
题目显然是个单调队列吗...可以O(N)做....但是那段时间被我用来练习平衡树了...
从前到后扫,每扫到一个就加进来,假如发现相差超过k,就一直在平衡树中删掉队头,总时间复杂度O(NlogN).....
贴一个初期平衡树代码
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstdlib>
#define N 3000001
using namespace std;
int si[N],ti[N],rd[N],l[N],r[N],a[N],root,cnt;
int b[N];
void pup(int x)
{
si[x]=si[l[x]]+si[r[x]]+ti[x];
}
void zxu(int &k)
{
int t=l[k];
l[k]=r[t];
r[t]=k;
si[t]=si[k];
pup(k);
k=t;
}
void yxu(int &k)
{
int t=r[k];
r[k]=l[t];
l[t]=k;
si[t]=si[k];
pup(k);
k=t;
}
void addadd(int &k,int x)
{
if(!k)
{
cnt++;
k=cnt;
a[cnt]=x;
si[cnt]=1;
ti[cnt]=1;
rd[cnt]=rand();
return;
}
si[k]++;
if(x==a[k])
{
ti[k]++;
return;
}
if(x<a[k])
{
addadd(l[k],x);
if(rd[l[k]]>rd[k]) zxu(k);
}
else
{
addadd(r[k],x);
if(rd[r[k]]>rd[k]) yxu(k);
}
}
void earase(int &k,int x)
{
if(!k) return;
if(a[k]==x)
{
if(ti[k]>1) ti[k]--,si[k]--;
else if(l[k]*r[k]==0) k=l[k]+r[k];
else if(rd[l[k]]>rd[r[k]])
{
zxu(k);
earase(k,x);
}
else if(rd[l[k]]<rd[r[k]])
{
yxu(k);
earase(k,x);
}
return;
}
if(x>a[k]) si[k]--,earase(r[k],x);
else if(x<a[k]) si[k]--,earase(l[k],x);
}
int rankgetnum(int k,int x)
{
if(x<=si[l[k]]) return rankgetnum(l[k],x);
if(x>si[l[k]]+ti[k]) return rankgetnum(r[k],x-si[l[k]]-ti[k]);
return a[k];
}
int main()
{
int n,m,c;
cin>>c>>m;
int i,j,k,x,now=0;
int ans=0;
for(i=1;i<=m;i++)
{
now++;
scanf("%d",&b[i]);
addadd(root,b[i]);
while(rankgetnum(root,now)-rankgetnum(root,1)>c)
{
now--;
earase(root,b[i-now]);
}
ans=max(ans,now);
}
cout<<ans;
}