【题目描述】
传送带
求使得max(al,al+1,…,ar)-(r-l+1)<=k的区间数目
【思路】
分治
预处理每个数小于它且互不相等的最左端和最右端
找跨过这个数的区间数目(按照长度较短的那一段枚举)
预处理有两种方式,RMQ倍增或者用单调栈来维护
其中互不相等可以用lst数组来实现
分治也有两种形式,普通的分治或者启发式分治
我用的是单调栈+普通分治
RMQ+启发式分治可见该博客传送带
【代码】
#include <iostream>
#include <string.h>
#include <queue>
#include <stdlib.h>
#include <stdio.h>
#include <stack>
#include <queue>
#include <cmath>
#include <algorithm>
using namespace std;
#define loop(i, x) for(int i = 0; i < x; ++i)
#define circle(i, st, en) for(int i = st; i <= en; ++i)
#define reverse(i, st, en) for(int i = st; i >= en; --i)
#define wh(t) while(t--)
#define mem(i, x) memset(i, x, sizeof(i))
#define ssc(x) scanf("%s", s)
#define dsc(x) scanf("%lld", &x)
#define lfsc(x) scanf("%lf", &x)
typedef long long ll;
const int MAXN=3e5+10;
const ll P=1e9+7;
const double eps=1e-10;
const double pi=acos(-1.0);
const int INF=0x3f3f3f3f;
int T;
int n,k;
int f[MAXN];
int a[MAXN];
int llst[MAXN];
int rlst[MAXN];
int pre[MAXN];
int lpos[MAXN];
int rpos[MAXN];
struct node{
int num;
int pos;
node(){}node(int num_,int pos_){num=num_;pos=pos_;}
};
stack<node> s;
ll solve(int l,int r){
if(l<=r) return r-l+1;
return 0;
}
ll dfs(int l,int r){
if(l>r) return 0;
int mid=(l+r)>>1;
ll res=0;
int lim=max(a[mid]-k,1);
if(mid-lpos[mid]>rpos[mid]-mid){
reverse(i,rpos[mid],mid)
res+=solve(max(llst[i],lpos[mid]),min(mid,i-lim+1));
}
else{
circle(i,lpos[mid],mid)
res+=solve(max(mid,i+lim-1),min(rlst[i],rpos[mid]));
}
res+=dfs(l,mid-1);
res+=dfs(mid+1,r);
return res;
}
int main(){
scanf("%d",&T);
wh(T){
scanf("%d%d",&n,&k);
while(!s.empty()) s.pop();
loop(i,MAXN) pre[i]=0;
circle(i,1,n){
scanf("%d",&a[i]);
llst[i]=pre[a[i]]+1,pre[a[i]]=i;
}
circle(i,1,n){
int pos=i;
llst[i]=max(llst[i],llst[i-1]);
while(!s.empty()&&s.top().num<=a[i]){
pos=s.top().pos;
s.pop();
}
s.push(node(a[i],pos));
lpos[i]=max(pos,llst[i]);
}
while(!s.empty()) s.pop();
loop(i,MAXN) pre[i]=n+1;
reverse(i,n,1) rlst[i]=pre[a[i]]-1,pre[a[i]]=i;
rlst[n+1]=n+1;
reverse(i,n,1){
int pos=i;
rlst[i]=min(rlst[i],rlst[i+1]);
while(!s.empty()&&s.top().num<=a[i]){
pos=s.top().pos;
s.pop();
}
s.push(node(a[i],pos));
rpos[i]=min(pos,rlst[i]);
}
printf("%lld\n",dfs(1,n));
}
return 0;
}