标签:opera query bsp int 元素 pen algo ++ tac
刚开始想出了一个分治做法,但是比较麻烦,需要分 4 中情况讨论.
后来偷看了一眼标签发现是线段树,然后就想出了这个线段树做法.
考虑序列以 $r$ 为右端点的答案,有 $\sum_{l=1}^{i} max(l,i)-min(l,i)=i-l$.
其中这个条件可以写成 $max(l,i)-min(l,i)+l=i$.
然后特别注意任何时候都满足不等式:$r-l \leqslant max(l,r)-min(l,r)$
考虑通过单调栈维护最大/最小值的过程中用线段树维护以 $i$ 为右端点,$j$ 为左端点的答案.
1. 假如新元素 $i$,则 $i$ 的贡献就是 $a[i]-a[i]+i=i$.
2. 维护最大值的单调栈要弹栈,则说明一段连续区间的最大值由原来的 $max.top() \Rightarrow a[i]$,则做区间加法.
3. 维护最小值时和最大值同理.
这样我们只需用线段树做区间加法就可以求出最小值个数,然后根据不等式:$r-l \leqslant max(l,r)-min(l,r)$ 可知最小值一定为 $i$,加上个数即可.
code:
#include <stack>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 300009
#define ll long long
#define lson now<<1
#define rson now<<1|1
#define inf 1000000000
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int n,a[N];
stack<int>mi,ma;
struct data {
int x,y;
data(int o=inf,int z=0) { x=o,y=z; }
data operator+(const data b) const {
data c;
c.x=min(x,b.x);
if(x==c.x) c.y+=y;
if(b.x==c.x) c.y+=b.y;
return c;
}
}s[N<<2];
int lazy[N<<2];
void mark(int now,int v) {
lazy[now]+=v;
s[now].x+=v;
}
void pushdown(int now) {
if(lazy[now]) {
mark(lson,lazy[now]);
mark(rson,lazy[now]);
lazy[now]=0;
}
}
void modify(int l,int r,int now,int p,int v) {
if(l==r) {
s[now].x=v;
s[now].y=1;
return;
}
pushdown(now);
int mid=(l+r)>>1;
if(p<=mid) modify(l,mid,lson,p,v);
else modify(mid+1,r,rson,p,v);
s[now]=s[lson]+s[rson];
}
void update(int l,int r,int now,int L,int R,int v) {
if(l>=L&&r<=R) {
mark(now,v);
return;
}
pushdown(now);
int mid=(l+r)>>1;
if(L<=mid) update(l,mid,lson,L,R,v);
if(R>mid) update(mid+1,r,rson,L,R,v);
s[now]=s[lson]+s[rson];
}
data query(int l,int r,int now,int L,int R) {
if(l>=L&&r<=R) {
return s[now];
}
pushdown(now);
int mid=(l+r)>>1;
if(L<=mid&&R>mid) {
return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R);
}
else if(L<=mid) return query(l,mid,lson,L,R);
else return query(mid+1,r,rson,L,R);
}
int pmi[N],pma[N];
int main() {
// setIO("input");
scanf("%d",&n);
int x,y,z;
for(int i=1;i<=n;++i) {
scanf("%d%d",&x,&y);
a[y]=x;
}
ll ans=0;
for(int i=1;i<=n;++i) {
modify(1,n,1,i,i);
z=i-1;
while(!mi.empty()&&a[i]<a[mi.top()]) {
update(1,n,1,pmi[mi.top()],z,a[mi.top()]-a[i]);
z=mi.top()-1;
mi.pop();
}
z=i-1;
while(!ma.empty()&&a[i]>a[ma.top()]) {
update(1,n,1,pma[ma.top()],z,a[i]-a[ma.top()]);
z=ma.top()-1;
ma.pop();
}
pmi[i]=mi.empty()?1:mi.top()+1;
pma[i]=ma.empty()?1:ma.top()+1;
mi.push(i);
ma.push(i);
ans+=s[1].y;
}
printf("%lld\n",ans);
return 0;
}
CF526F Pudding Monsters 线段树+单调栈
标签:opera query bsp int 元素 pen algo ++ tac
原文地址:https://www.cnblogs.com/guangheli/p/13282321.html