# Pudding Monsters

$n \le 3 \times 10^5$

## 题解

https://www.luogu.com.cn/blog/xht37/solution-cf526f

CO int N=3e5+10;
int a[N];
vector<int> mx={0},mn={0};
map<int,int> pos;

int val[4*N],tag[4*N],cnt[4*N];

#define lc (x<<1)
#define rc (x<<1|1)
#define mid ((l+r)>>1)
IN void push_up(int x){
val[x]=min(val[lc],val[rc]);
cnt[x]=(val[lc]==val[x]?cnt[lc]:0)+(val[rc]==val[x]?cnt[rc]:0);
}
IN void put_tag(int x,int v){
val[x]+=v,tag[x]+=v;
}
IN void push_down(int x){
if(tag[x]){
put_tag(lc,tag[x]),put_tag(rc,tag[x]);
tag[x]=0;
}
}
void build(int x,int l,int r){
cnt[x]=r-l+1;
if(l==r) return;
build(lc,l,mid),build(rc,mid+1,r);
}
void modify(int x,int l,int r,int ql,int qr,int v){
if(ql<=l and r<=qr) return put_tag(x,v);
push_down(x);
if(ql<=mid) modify(lc,l,mid,ql,qr,v);
if(qr>mid) modify(rc,mid+1,r,ql,qr,v);
push_up(x);
}
#undef lc
#undef rc
#undef mid

int main(){
build(1,1,n);
int64 ans=0;
for(int i=1;i<=n;++i){
for(;mx.size()>1 and a[mx.back()]<=a[i];mx.pop_back())
modify(1,1,n,mx[mx.size()-2]+1,mx.back(),-a[mx.back()]);
modify(1,1,n,mx.back()+1,i,a[i]);
mx.push_back(i);
for(;mx.size()>1 and a[mn.back()]>=a[i];mn.pop_back())
modify(1,1,n,mn[mn.size()-2]+1,mn.back(),a[mn.back()]);
modify(1,1,n,mn.back()+1,i,-a[i]);
mn.push_back(i);
modify(1,1,n,pos[a[i]]+1,i,-1);
pos[a[i]]=i;
ans+=cnt[1];
//		cerr<<i<<" cnt="<<cnt[1]<<endl;
}
printf("%lld\n",ans);
return 0;
}


# Good Subsegments

$q$次询问，每次问$[l,r]$内，有多少子区间是好的？

$1\le n,q\le 1.2*10^5$

## 题解

https://www.luogu.com.cn/blog/litble-blog/solution-cf997e

CO int N=1.2e5+10;
int val[4*N],cnt[4*N],tag[4*N],tim[4*N];
int64 sum[4*N];

#define lc (x<<1)
#define rc (x<<1|1)
#define mid ((l+r)>>1)
IN void push_up(int x){
val[x]=min(val[lc],val[rc]);
cnt[x]=(val[lc]==val[x]?cnt[lc]:0)+(val[rc]==val[x]?cnt[rc]:0);
sum[x]=sum[lc]+sum[rc];
}
IN void put_tag(int x,int v){
val[x]+=v,tag[x]+=v;
}
IN void put_tim(int x,int v){
sum[x]+=(int64)cnt[x]*v,tim[x]+=v;
}
IN void push_down(int x){
if(tag[x]){
put_tag(lc,tag[x]),put_tag(rc,tag[x]);
tag[x]=0;
}
if(tim[x]){
if(val[lc]==val[x]) put_tim(lc,tim[x]);
if(val[rc]==val[x]) put_tim(rc,tim[x]);
tim[x]=0;
}
}
void build(int x,int l,int r){
val[x]=l,cnt[x]=1; // offset
if(l==r) return;
build(lc,l,mid),build(rc,mid+1,r);
}
void modify(int x,int l,int r,int ql,int qr,int v){
if(ql<=l and r<=qr) return put_tag(x,v);
push_down(x);
if(ql<=mid) modify(lc,l,mid,ql,qr,v);
if(qr>mid) modify(rc,mid+1,r,ql,qr,v);
push_up(x);
}
int64 query(int x,int l,int r,int ql,int qr){
if(ql<=l and r<=qr) return sum[x];
push_down(x);
if(qr<=mid) return query(lc,l,mid,ql,qr);
if(ql>mid) return query(rc,mid+1,r,ql,qr);
return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr);
}
#undef lc
#undef rc
#undef mid

int a[N];
vector<int> mx={0},mn={0};
vector<pair<int,int> > q[N];
int64 ans[N];

int main(){
for(int i=1;i<=m;++i){
q[r].push_back({l,i});
}
build(1,1,n);
for(int i=1;i<=n;++i){
for(;mx.size()>1 and a[mx.back()]<=a[i];mx.pop_back())
modify(1,1,n,mx[mx.size()-2]+1,mx.back(),a[i]-a[mx.back()]);
mx.push_back(i);
for(;mn.size()>1 and a[mn.back()]>=a[i];mn.pop_back())
modify(1,1,n,mn[mn.size()-2]+1,mn.back(),a[mn.back()]-a[i]);
mn.push_back(i);
put_tag(1,-1);
put_tim(1,1);
for(CO pair<int,int>&x:q[i]) ans[x.second]=query(1,1,n,x.first,i);
}
for(int i=1;i<=m;++i) printf("%lld\n",ans[i]);
return 0;
}


posted on 2020-07-08 20:28  autoint  阅读(105)  评论(0编辑  收藏