标签:
题意: 给你一个序列 和 K, 求有多少区间满足 区间最大值和最小值的差 小于 K
RMQ问题…………..枚举起点,二分终点
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<map> #include<set> #include<vector> #include<queue> #include<stack> //#include<bits/std c++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; const LL MOD = 1e7 + 7; const LL maxn = 100000 + 131; int MaxNum[maxn][20], MinNum[maxn][20]; int Num[maxn]; int n,k; int GetK(int l,int r) { int k = log2(double(r-l+1)); int a = max(MaxNum[l][k],MaxNum[r-(1<<k)+1][k]); int b = min(MinNum[l][k],MinNum[r-(1<<k)+1][k]); return a-b; } // 返回最大值与最小值的差 int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&k); for(int i = 1; i <= n; ++i) { scanf("%d",&Num[i]); MaxNum[i][0] = MinNum[i][0] = Num[i]; } for(int j = 1; (1<<j) <= n; ++j) { for(int i = 1; i +(1<<j)-1 <= n; ++i) { LL p = (1<<(j-1)); MinNum[i][j] = min(MinNum[i][j-1],MinNum[i+p][j-1]); MaxNum[i][j] = max(MaxNum[i][j-1],MaxNum[i+p][j-1]); } } LL ans = 0; for(int i = 1; i <= n; ++i) { int l = i, r = n; while(l +1 < r) { int m = (l + r) >> 1; if(GetK(i,m)< k) l = m;//要注意判断范围,是起点到m………… else r = m; } if(GetK(i,r)< k) ans += (r-i+1); else ans += (l-i+1); } printf("%I64d\n",ans); } }
标签:
原文地址:http://www.cnblogs.com/aoxuets/p/4701055.html