发现枚举+二分更好!
我做得复杂了,竟然两个都是从左边开始枚举。找最大最小用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; }
时间: 2024-12-21 23:00:36