HDU 5289
发现枚举+二分更好!
我做得复杂了,竟然两个都是从左边开始枚举。找最大最小用ST算法吧。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define LL long long
using namespace std;
const int MAX=100050;
int f_min[MAX][20];
int f_max[MAX][20];
int num[MAX],n,dif;
void pre_init(){
int k=(int)(log((double)n)/log(2.0));
for(int i=0;i<n;i++) f_min[i][0]=num[i],f_max[i][0]=num[i];
for(int j=1;j<=k;j++){
for(int i=0;i + (1 << j) - 1<n;i++){
f_min[i][j]=min(f_min[i][j-1],f_min[i+(1<<(j-1))][j-1]);
f_max[i][j]=max(f_max[i][j-1],f_max[i+(1<<(j-1))][j-1]);
}
}
}
int find_min(int i,int j){
int k = (int)(log(double(j-i+1)) / log(2.0));
return min(f_min[i][k], f_min[j - (1<<k) + 1][k]);
}
int find_max(int i,int j){
int k = (int)(log(double(j-i+1)) / log(2.0));
return max(f_max[i][k], f_max[j - (1<<k) + 1][k]);
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&dif);
for(int i=0;i<n;i++)
scanf("%d",&num[i]);
pre_init();
LL ans=0;
int l=0,r=0;
int dmin=num[0],umax=num[0]; bool flag=true;
while(l<n&&r<n){
if(flag){
while(r<n){
r++;
if(r==n){
r--;
break;
}
dmin=find_min(l,r);
umax=find_max(l,r);
if(umax-dmin>=dif){
r--;
break;
}
}
// cout<<"true:"<<l<<" "<<r<<endl;
flag=false;
ans+=r-l+1;
}
else{
while(l<=r){
l++;
if(l>r){
break;
}
if(dmin!=find_min(l,r)||umax!=find_max(l,r)){
break;
}
else{
ans+=r-l+1;
}
}
// cout<<"false:"<<l<<" "<<r<<endl;
flag=true;
}
}
printf("%lld\n",ans);
}
return 0;
}

浙公网安备 33010602011771号