题目链接:
点击打开链接
代码:
#include<iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 100005;
int a[maxn],q_max[maxn][50],q_min[maxn][50];
int n,k;
void rmq(){
for(int j=0; (1<<j)<=n; j++){
for(int i=1;i<=n;i++){
if(j==0){
q_max[i][0] = q_min[i][0] = a[i];
}
else {
if(i+(1<<j)-1 <= n){
q_max[i][j] = max(q_max[i][j-1], q_max[i+(1<<(j-1))][j-1]);
q_min[i][j] = min(q_min[i][j-1], q_min[i+(1<<(j-1))][j-1]);
}
}
}
}
}
int Q(int l, int r, bool is_q_max){
int kk=0;
while(l+(1<<(kk+1))-1 <= r) kk++;
if(is_q_max == true)return max(q_max[l][kk],q_max[r-(1<<kk)+1][kk]);
else return min(q_min[l][kk],q_min[r-(1<<kk)+1][kk]);
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&k);
for(int i=1; i<=n; i++){
scanf("%d",&a[i]);
}
rmq();
long long ans=0;
for(int i=1; i<=n; i++){
if(Q(i,n,true)-Q(i,n,false) < k) {ans+=(n-i+1);continue;}
int l=i, r=n, mid;
while(l<r-1){
mid = (l+r)>>1;
if(Q(i,mid,true)-Q(i,mid,false) >= k) r = mid;
else l = mid;
}
ans += (l-i+1);
}
printf("%lld\n",ans);
}
return 0;
}
wa两次,因为没用long long
复习一下rmq。dp[i][j]表示从i开始的2^j长度中的最值。由此可列出转移方程。代码里有。
稍微改了一下,这个更好一点
#include<iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 100005;
int a[maxn],q_max[maxn][50],q_min[maxn][50];
int n,k;
void rmq(){
for(int j=0; (1<<j)<=n; j++){
for(int i=1;i<=n;i++){
if(j==0){
q_max[i][0] = q_min[i][0] = a[i];
}
else {
if(i+(1<<j)-1 <= n){
q_max[i][j] = max(q_max[i][j-1], q_max[i+(1<<(j-1))][j-1]);
q_min[i][j] = min(q_min[i][j-1], q_min[i+(1<<(j-1))][j-1]);
}
else break;
}
}
}
}
int Q(int l, int r, bool is_q_max){
int kk = (int)(log(1.0*(r-l+1))/log(2.0));
if(is_q_max == true)return max(q_max[l][kk],q_max[r-(1<<kk)+1][kk]);
else return min(q_min[l][kk],q_min[r-(1<<kk)+1][kk]);
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&k);
for(int i=1; i<=n; i++){
scanf("%d",&a[i]);
}
rmq();
long long ans=0;
for(int i=1; i<=n; i++){
if(Q(i,n,true)-Q(i,n,false) < k) {ans+=(n-i+1);continue;}
int l=i, r=n, mid;
while(l<r-1){
mid = (l+r)>>1;
if(Q(i,mid,true)-Q(i,mid,false) >= k) r = mid;
else l = mid;
}
ans += (l-i+1);
}
printf("%lld\n",ans);
}
return 0;
}