Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1673 Accepted Submission(s): 807
#include <iostream> #include <cstdio> #include <cmath> #include <cstdlib> #define LL long long #define maxn 110000 using namespace std; LL k; int n; LL a[maxn]; int up[maxn]; int down[maxn]; int Head1,Tail1; int Head2,Tail2; int Front; void solve() { LL ans=1; Head1=0; Tail1=0; Head2=0; Tail2=0; up[Tail1++]=0; down[Tail2++]=0; Front=0; for(int i=1;i<n;i++) { while(Head1<Tail1 && a[up[Tail1-1]]>a[i]) Tail1--; up[Tail1++]=i; //存入决策,序号 while(Head2<Tail2 && a[down[Tail2-1]]<a[i]) Tail2--; down[Tail2++]=i; while(a[down[Head2]]-a[up[Head1]]>=k) { if(up[Head1]==Front) Head1++; //删掉队首 if(down[Head2]==Front) Head2++; Front++; } ans+=i-Front+1; // printf("%d ",i-Front+1); } printf("%lld\n",ans); } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%lld",&n,&k); for(int i=0;i<n;i++) { scanf("%lld",&a[i]); } solve(); } return 0; }
由于区间越大,差值越大,所以可以枚举起点,二分查找终点的坐标,ans加上(R-i)+1即可。
#include <iostream> #include <cstdio> #include <cmath> #include <cstdlib> #define LL long long #define maxn 110000 #include <cstring> using namespace std; LL k; int n; LL a[maxn]; LL d[maxn][35]; //d数组代表最小值,以i开始,长度为2^j LL D[maxn][35]; //d数组代表最大值 void init() { memset(d,0,sizeof(d)); } void RMQ_init() { for(int j=1; (1<<j) <=n ;j++) //枚举长度 { for(int i=0;(i+ (1<<j))-1<n;i++) //(1<<j)为长度 { d[i][j]= min(d[i][j-1],d[i+ (1<<(j-1)) ][j-1]); D[i][j]= max(D[i][j-1],D[i+ (1<<(j-1))][j-1]); //printf("%d %d %lld %lld\n",i,j,d[i][j],D[i][j]); // cout<<endl; } } } LL q(int L,int R) { int k=0; while((1<<(k+1)) <= (R-L+1)) k++; LL Min=min(d[L][k],d[R-(1<<k)+1][k]); LL Max=max(D[L][k],D[R-(1<<k)+1][k]); return Max-Min; } void solve() { LL ans=0; for(int i=0;i<n;i++) { int L=i,R=n-1; while(L<=R) //最终L为第一个不满足的点,由于退出循环是R>L,所以R为最后一个满足的点 { int Mid=(L+R)>>1; if(q(i,Mid) < k) { L=Mid+1; } else R=Mid-1; } ans+=(R-i)+1; // printf("%d %d %d\n",i,R,(R-i)+1); } printf("%lld\n",ans); } int main() { int t; scanf("%d",&t); while(t--) { init(); scanf("%d%lld",&n,&k); for(int i=0;i<n;i++) { scanf("%lld",&a[i]); d[i][0]=a[i]; D[i][0]=a[i]; } RMQ_init(); // printf("%lld %lld %lld %lld\n",d[0][1],D[0][1],q(1,2),q(0,2)); solve(); } return 0; }