http://acm.hdu.edu.cn/showproblem.php?pid=5289
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]
/** hdu5289||2015多校联合第一场1002贪心+RMQ 题目大意:找出连续子区间,其最大最小值只差小于k 解题思路:用rmq维护区间最大最小值只差,贪心扫一遍即可,复杂度O(nlogn) */ #include <stdio.h> #include <algorithm> #include <iostream> #include <string.h> using namespace std; const int N=200005; int a[N],n,m; int dp1[N][30]; int dp2[N][30]; void RMQ_init(int n) { for(int i=1;i<=n;i++) { dp1[i][0]=a[i]; dp2[i][0]=a[i]; } for(int j=1;(1<<j)<=n;j++) { for(int i=1;i+(1<<j)-1<=n;i++)///白书上的模板,次行稍作改动,否则dp数组要扩大一倍防止RE { dp1[i][j]=max(dp1[i][j-1],dp1[i+(1<<(j-1))][j-1]); dp2[i][j]=min(dp2[i][j-1],dp2[i+(1<<(j-1))][j-1]); } } } int rmq(int x,int y) { int k=0; while((1<<(k+1))<=y-x+1)k++; return max(dp1[x][k],dp1[y-(1<<k)+1][k])-min(dp2[x][k],dp2[y-(1<<k)+1][k]); } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } RMQ_init(n); int k=1; long long sum=0; for(int i=1;i<=n;i++) { while(rmq(k,i)>=m&&k<i)k++; sum+=(i-k+1); // printf("dis i k i-k+1:%d %d %d %d\n",rmq(k,i),i,k,i-k+1); } printf("%I64d\n",sum); } return 0; }