AT_abc444_e 题解
双指针大法好,耶。
注意到若区间
升序枚举右端点
思路没毛病,但是有一个问题,如何判断当前的区间情况插入 set 维护,但是数列中可能有重复元素,因此改用 multiset。只要在 multiset 内第一个不大于
判断的时候,因为总是要处理边界情况,做两次二分有些麻烦还容易出错,这里提供一种另外的方案:你只需要判断 multiset 内第一个不小于
于是这道题就结束啦。噢对了,记得要开 long long 喔!
#include<bits/stdc++.h>
#define LL long long
#define UInt unsigned int
#define ULL unsigned long long
#define LD long double
#define pii pair<int,int>
#define pLL pair<LL,LL>
#define pDD pair<LD,LD>
#define fr first
#define se second
#define pb push_back
#define isr insert
using namespace std;
const int N = 4e5+5;
LL n,D,a[N],Ans;
multiset<LL> st;
LL read(){
LL su=0,pp=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')pp=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){su=su*10+ch-'0';ch=getchar();}
return su*pp;
}
int main(){
n=read(),D=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int l=1,r=1;r<=n;r++){
while(!st.empty()){
auto it=st.lower_bound(a[r]-D+1);
if(it==st.end()||(*it)>a[r]+D-1)break;
st.erase(st.find(a[l]));l++;
}st.insert(a[r]),Ans+=r-l+1;
}cout<<Ans<<"\n";
return 0;
}
如果本篇题解对你有帮助的话,麻烦你点一个小小的赞,真是太感谢啦!