先把一维拍扁,那么问题就转化成了求这个的个数,\(\max-\min= r-l\)
变一下,\(\max - \min -len=-1\)
枚举右端点,发现每次一定存在-1,然后可以在线段树上维护这个式子的最小值及个数
每次单调栈退栈和进栈时,在线段树上更新值
#include<bits/stdc++.h> using namespace std; #define int long long const int inf=0x3ffffffffffffff; const int N=3e5+11; struct tree{ int l,r; int num; int sum,lazy; }tre[4*N]; struct sta_{ int i; int l,x; }sp[N],sd[N]; int n; int ans; int tp,td; int a[N]; inline int read() { int s=0; char ch=getchar(); while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') { s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); } return s; } void pushdown(int i) { if(tre[i].l==tre[i].r)return; tre[i<<1].lazy+=tre[i].lazy; tre[i<<1|1].lazy+=tre[i].lazy; tre[i<<1].sum+=tre[i].lazy; tre[i<<1|1].sum+=tre[i].lazy; tre[i].lazy=0; return; } void update(int i) { tre[i].sum=tre[i<<1].sum,tre[i].num=tre[i<<1].num; if(tre[i<<1|1].sum==tre[i<<1].sum) tre[i].num+=tre[i<<1|1].num; if(tre[i<<1|1].sum<tre[i<<1].sum) tre[i].sum=tre[i<<1|1].sum,tre[i].num=tre[i<<1|1].num; return; } void insert(int i,int l,int r,int sum) { if(tre[i].lazy) pushdown(i); if(tre[i].l>=l&&tre[i].r<=r) { tre[i].sum+=sum; tre[i].lazy+=sum; return; } int mid=(tre[i].l+tre[i].r)>>1; if(l<=mid) insert(i<<1,l,r,sum); if(r>mid) insert(i<<1|1,l,r,sum); update(i); return; } void build(int i,int l,int r) { tre[i].l=l; tre[i].r=r; if(l==r) {tre[i].num=1;return;} int mid=(l+r)>>1; build(i<<1,l,mid); build(i<<1|1,mid+1,r); return; } signed main() { n=read(); for(int i=1;i<=n;++i) a[read()]=read(); build(1,1,n); for(int i=1;i<=n;++i) { int lp=i,ld=i; while(tp&&sp[tp].x<a[i]) insert(1,sp[tp].l,sp[tp].i,-sp[tp].x),lp=sp[tp].l,--tp; while(td&&sd[td].x>a[i]) insert(1,sd[td].l,sd[td].i,sd[td].x),ld=sd[td].l,--td; if(i-1) insert(1,lp,i-1,a[i]),insert(1,ld,i-1,-a[i]),insert(1,1,i-1,-1); insert(1,i,i,-1); sp[++tp]=(sta_){i,lp,a[i]}; sd[++td]=(sta_){i,ld,a[i]}; ans+=tre[1].num; } cout<<ans<<endl; return 0; }