题目连接:https://www.luogu.org/problem/show?pid=CF526F
判断一段区间是否能连续,只要判断是否满足 m a x − m i n = r − l max-min=r-l max−min=r−l即可.
也即判断区间是否满足 m a x − m i n + l = r max-min+l = r max−min+l=r.
先天有 m a x − m i n + l ≥ r max-min+l \ge r max−min+l≥r
因此我们可以考虑枚举区间端点 r r r,然后使用线段树维护左边所有区间(每个区间用左端点唯一标识)的 l + m a x − m i n l+max-min l+max−min的值.
我们还需要线段树满足求线段内最小值是谁,最小值有多少个的功能.
考虑到区间右端点向右移动的过程中,原有的区间再加上 r r r形成的新区间的 m a x max max不会变小, m i n min min值不会变大.
而 m a x max max变大也会是一批区间一起增大,增量也是相同的,因此可以转化为区间修改操作.
我们可以用 2 2 2个单调栈来维护当前的最大值序列,和最小值序列.
每次将 r r r点加入左边所有的区间,从而形成新的区间,根据单调栈保存的信息,确定出哪些区间的最大值或者是最小值需要被修改,然后进行区间修改.
询问时候,直接查询 [ 1 , r ] [1,r] [1,r]内最小值为 0 0 0的个数,算贡献.
#include
#include
#include
#define pr(x) std::cout << #x << ':' << x << std::endl
#define rep(i,a,b) for(int i = a;i <= b;++i)
#define clr(x) memset(x,0,sizeof(x))
#define setinf(x) memset(x,0x3f,sizeof(x))
const int N = 300007,inf = 1e9;
int n,m;
typedef std::pair<int,int> pii;
int a[N];
struct node{
int val,cnt,tag,len;
node(int val = 0,int cnt = 1,int tag = 0,int len = 1):val(val),cnt(cnt),tag(tag),len(len){}
}ns[N<<2];
//线段树维护的是区间最小值以及最小值的个数
inline void pushdown(int o) {
if(ns[o].tag) {
ns[o<<1].val += ns[o].tag;
ns[o<<1|1].val += ns[o].tag;
ns[o<<1].tag += ns[o].tag;
ns[o<<1|1].tag += ns[o].tag;
ns[o].tag = 0;
}
}
inline node maintain(node &lch,node &rch) {
node res = node(std::min(lch.val,rch.val),0,0,lch.len+rch.len);
if(lch.val == res.val) res.cnt += lch.cnt;
if(rch.val == res.val) res.cnt += rch.cnt;
return res;
}
inline void change(int o,int l,int r,int cl,int cr,int val) {
if(cl <= l && r <= cr) {
ns[o].tag += val;
ns[o].val += val;
return ;
}
if(r < cl || cr < l) return;
int mid = (l + r) >> 1;
pushdown(o);
change(o<<1,l,mid,cl,cr,val);
change(o<<1|1,mid+1,r,cl,cr,val);
ns[o] = maintain(ns[o<<1],ns[o<<1|1]);
}
inline node query(int o,int l,int r,int ql,int qr) {
if(ql <= l && r <= qr)
return ns[o];
if(r < ql || qr < l)
return node(inf,1,0,0);
int mid = (l + r) >> 1;
pushdown(o);
node lch = query(o<<1,l,mid,ql,qr);
node rch = query(o<<1|1,mid+1,r,ql,qr);
return maintain(lch,rch);
}
inline void build(int o,int l,int r) {
if(l == r) {
ns[o] = node(0,1,0,1);
return ;
}
int mid = (l + r) >> 1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
ns[o] = maintain(ns[o<<1],ns[o<<1|1]);
}
pii mx[N],mi[N];
int topx,topi;
int main() {
std::cin >> n;
build(1,1,n);
rep(i,1,n) {
int idx,y;
std::cin >> idx >> y;
a[idx] = y;
}
long long ans = 0;
rep(i,1,n) {
change(1,1,n,i,i,i);
while(topx > 0 && mx[topx].first < a[i]) {
change(1,1,n,mx[topx-1].second+1,mx[topx].second,a[i] - mx[topx].first);
topx--;
}
mx[++topx] = (pii){a[i],i};
while(topi > 0 && mi[topi].first > a[i]) {
change(1,1,n,mi[topi-1].second+1,mi[topi].second,mi[topi].first - a[i]);
topi--;
}
mi[++topi] = (pii){a[i],i};
change(1,1,n,1,i,-i);
node res = query(1,1,n,1,i);
ans += res.cnt;
change(1,1,n,1,i,i);
}
std::cout << ans << std::endl;
return 0;
}