#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn= 200010;
const int maxn2=8000000;
int n,a[maxn],mx[maxn][20],mn[maxn][20],ql[maxn],qr[maxn];
/*struct Node{
int l,r;
int lenth;
}node[maxn2];*用结构体数组会MLE,起码开到10^10次方
void init(){
int m=floor(log((double)n)/log(2.0));
for(int i=1;i<=n;i++) mx[i][0]=mn[i][0]=a[i];
for(int i=1;i<=m;i++)
for(int j=n;j>0;j--){
mx[j][i]=mx[j][i-1];
mn[j][i]=mn[j][i-1];
if(j+(1<<(i-1))<=n){
mx[j][i]=max(mx[j][i],mx[j+(1<<(i-1))][i-1]);
mn[j][i]=min(mn[j][i],mn[j+(1<<(i-1))][i-1]);
//cout<<"mx:"<<mx[j][i]<<"mn:"<<mn[j][i]<<endl;
}
}
}
/*bool cmp1(const Node &a,const Node &b)
{
return a.lenth>b.lenth;
}*/
int query(int l,int r){
int m=floor(log((double)(r-l+1))/log(2.0));
int Max=max(mx[l][m],mx[r-(1<<m)+1][m]);
int Min=min(mn[l][m],mn[r-(1<<m)+1][m]);
//cout<<"1:"<<mx[l][m]<<"2:"<<mx[r-(1<<m)+1][m]<<endl;
//cout<<"m:"<<Max<<"mi:"<<Min<<endl;
return Max-Min;
}
int main()
{ int k,maxs,cnt,flag,ans;
while(scanf("%d%d",&n,&k)!=EOF)
{
cnt=0;
ans=0;
//memset(node,0,sizeof(node));
memset(a,0,sizeof(a));
memset(mx,0,sizeof(mx));
memset(mn,0,sizeof(mn));
for(int k=1;k<=n;k++)
scanf("%d",&a[k]);
init();
int i;
int j;
for(i=j=1;j<=n;i++)
{
if(j<i)
j=i;
while(j<=n&&query(i,j)<=k)///遍所有可能区间尽量不要用嵌套for循环,会炸掉
++j;
if(j-i>ans)
ans=j-i,ql[0]=i,qr[0]=j-1,flag=1;
else if(j-i==ans)
ql[flag]=i,qr[flag++]=j-1;
}///以上这种遍历方法值得学习,虽然写得多的但是复杂度大大减少,不能偷懒!
//sort(node+1,node+num,cmp1);
//maxs=node[1].lenth;
//cout<<"ma:"<<maxs<<endl;
/*if(maxs==1)
printf("2 ");
else*/
printf("%d %d\n",ans,flag);
/*for(int i=1;i<num;i++)
{
if(node[i].lenth==maxs)
{
cnt++;
}
}
printf("%d\n",cnt);*/
for(int i=0;i<flag;i++)
printf("%d %d\n",ql[i],qr[i]);
}
return 0;
}
整体思路比较简单清晰,但是需要注意细节上的算法优化。
1、遇到大数据时尽量不要用结构体数组,改用两个数组来存储。
2、区间的遍历尽量不要用嵌套for。