CF526F

先把一维拍扁,那么问题就转化成了求这个的个数,\(\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;
}
posted @ 2021-10-13 06:13  sitiy  阅读(35)  评论(0编辑  收藏  举报