Assignment HDU
阿新 • • 發佈:2018-12-15
- 題意:給出一個數列,問其中存在多少連續子序列,子序列的最大值-最小值<m。
- 思路:列舉終點,尺取起點O(1)rmq倍增查詢
-
#include<iostream> #include<cstring> #include<cmath> #include<stdio.h> using namespace std; #define maxn 200000 #define maxm 30 #define ll long long int dpmin[maxn][maxm]; int dpmax[maxn][maxm]; int a[maxn],n,q,m,k,t; void rmqinit() { for(int j=1; (1<<j)<=n; j++) for(int i=1; i+(1<<j)<n+2; i++) { dpmin[i][j]=min(dpmin[i][j-1],dpmin[i+(1<<(j-1))][j-1]); dpmax[i][j]=max(dpmax[i][j-1],dpmax[i+(1<<(j-1))][j-1]); } } int rmqmin(int l,int r) { int k=log(r-l+1)/log(2); return min(dpmin[l][k],dpmin[r-(1<<k)+1][k]); } int rmqmax(int l,int r) { int k=log(r-l+1)/log(2); return max(dpmax[l][k],dpmax[r-(1<<k)+1][k]); } int main() { scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); dpmin[i][0]=dpmax[i][0]=a[i]; } rmqinit(); ll ans=0; k=1; for(int i=1; i<=n; i++) { while(rmqmax(k,i)-rmqmin(k,i)>=m&&k<i)k++; ans+=(i-k+1); } printf("%lld\n",ans); } return 0; }