http://codeforces.com/problemset/problem/6/E
给出数列 求最长连续子序列:最大值与最小值只差不超过k,如果多组都输出 并输出每组序列的头尾序号
线段树存区间最大最小值 再枚举区间
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int MAXN=100005;
int maxx[MAXN<<2];
int minn[MAXN<<2];
int ql[MAXN],qr[MAXN];
void build(int l,int r,int rt)
{
if(l==r)
{
scanf("%d",&maxx[rt]);
minn[rt]=maxx[rt];
return ;
}
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
}
int search_max(int ll,int rr,int l,int r,int rt)
{
if(ll<=l&&rr>=r)
{
return maxx[rt];
}
int ans=-1e7;
int m=(l+r)>>1;
if(ll<=m)
ans=max(ans,search_max(ll,rr,l,m,rt<<1));
if(rr>m)
ans=max(ans,search_max(ll,rr,m+1,r,rt<<1|1));
return ans;
}
int search_min(int ll,int rr,int l,int r,int rt)
{
if(ll<=l&&rr>=r)
{
return minn[rt];
}
int ans=1e7;
int m=(l+r)>>1;
if(ll<=m)
ans=min(ans,search_min(ll,rr,l,m,rt<<1));
if(rr>m)
ans=min(ans,search_min(ll,rr,m+1,r,rt<<1|1));
return ans;
}
int main()
{
int n,k,i,j;
while(~scanf("%d%d",&n,&k))
{
build(1,n,1);
int ans=0;
int t=0;
for(i=1,j=1;j<=n;i++)
{
if(j<i)
j=i;
while(j<=n&&(search_max(i,j,1,n,1)-search_min(i,j,1,n,1)<=k))
j++;
if(j-i>ans)
ans=j-i,ql[0]=i,qr[0]=j-1,t=1;
else if(j-i==ans)
ql[t]=i,qr[t++]=j-1;
}
printf("%d %d\n",ans,t);
for(i=0;i<t;i++)
printf("%d %d\n",ql[i],qr[i]);
}
return 0;
}