2 4 2 3 1 2 4 10 5 0 3 4 5 2 1 6 7 8 9
5 28HintFirst Sample, the satisfied groups include:[1,1]、[2,2]、[3,3]、[4,4] 、[2,3]
这题有多种做法,但思路差不多,我的做法是依次枚举左端点或者右端点,然后二分查找所能达到的最右边,然后累加起来。
方法一:用树状数组或者rmq枚举左端点,然后二分查找满足条件的最右端点。
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<set> #include<queue> #include<stack> #include<string> #include<algorithm> using namespace std; #define maxn 100060 #define ll long long #define inf 2000000000 int a[maxn],b1[maxn],b2[maxn];/*b1最小值,b2最大值*/ int lowbit(int x){ return x&(-x); } void update1(int pos,int num) { while(pos<=maxn){ b1[pos]=min(b1[pos],num);pos+=lowbit(pos); } } int question1(int pos) { int num=inf; while(pos>0){ num=min(b1[pos],num);pos-=lowbit(pos); } return num; } void update2(int pos,int num) { while(pos<=maxn){ b2[pos]=max(b2[pos],num);pos+=lowbit(pos); } } int question2(int pos) { int num=-1; while(pos>0){ num=max(b2[pos],num);pos-=lowbit(pos); } return num; } int main() { int n,m,i,j,T,k,l,mid,r; ll ans; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&k); for(i=1;i<=n;i++){ b1[i]=inf;b2[i]=-1; scanf("%d",&a[i]); } ans=0; for(i=n;i>=1;i--){ update1(i,a[i]); update2(i,a[i]); l=i;r=n; while(l<=r){ mid=(l+r)/2; if(question2(mid)-question1(mid)>=k){ r=mid-1; } else l=mid+1; } //printf("%d %d %d\n",i,l,r); if(r>=i) ans+=(ll)(r-i+1); /*printf("%lld\n",ans);*/ } printf("%lld\n",ans); } return 0; }
代码二:维护两个单调队列,分别维护最大值和最小值,依次枚举右端点,然后找到符合条件的左端点。(这个方法速度是最快的,只需243ms,惊!)
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<string> #include<algorithm> using namespace std; #define maxn 100060 #define ll long long int q1[1111111][2],q2[1111111][2]; int a[maxn]; int main() { int n,m,i,j,k,front1,front2,rear1,rear2,l,r,T; ll ans; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&k); ans=0; front1=front2=1;rear1=rear2=0;l=1; for(i=1;i<=n;i++){ scanf("%d",&a[i]); while(front1<=rear1 && q1[rear1][0]>=a[i]){ rear1--; } rear1++;q1[rear1][0]=a[i];q1[rear1][1]=i; while(front2<=rear2 && q2[rear2][0]<=a[i]){ rear2--; } rear2++;q2[rear2][0]=a[i];q2[rear2][1]=i; while(front1<=rear1 && front2<=rear2 && q2[front2][0]-q1[front1][0]>=k){ l=min(q2[front2][1],q1[front1][1])+1; if(q2[front2][1]<q1[front1][1]){ front2++; } else if(q2[front2][1]>q1[front1][1]){ front1++; } else{ front1++;front2++; } } ans+=i-l+1; /*printf("%d %d %lld\n",i,l,ans);*/ } printf("%lld\n",ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/kirito_acmer/article/details/47722913