区间取max/min的线段树(势能分析啦啦啦)
题目的话。。最假女选手。。
```C++
#include
#include
#include
#define ll long long
using namespace std;
const int N=5*(1e5)+10,inf=2147483647;
int a[N];
namespace Seg{/*{{{*/
const int N=::N*4;
int ch[N][2],cntmx[N],cntmn[N],mx[N],smx[N],mn[N],smn[N];
ll sum[N],sumtag[N];
int n,tot;
void pushup(int x){
sum[x]=sum[ch[x][0]]+sum[ch[x][1]];
smx[x]=-inf;
smn[x]=inf;
if (mx[ch[x][0]]==mx[ch[x][1]]){
mx[x]=mx[ch[x][0]];
cntmx[x]=cntmx[ch[x][0]]+cntmx[ch[x][1]];
smx[x]=max(smx[ch[x][0]],smx[ch[x][1]]);
}
else{
int dw,up;
if (mx[ch[x][0]]>mx[ch[x][1]]) dw=1,up=0;
else dw=0,up=1;
mx[x]=mx[ch[x][up]];
cntmx[x]=cntmx[ch[x][up]];
smx[x]=max(smx[ch[x][up]],mx[ch[x][dw]]);
}
if (mn[ch[x][0]]==mn[ch[x][1]]){
mn[x]=mn[ch[x][0]];
cntmn[x]=cntmn[ch[x][0]]+cntmn[ch[x][1]];
smn[x]=min(smn[ch[x][0]],smn[ch[x][1]]);
}
else{
int dw,up;
if (mn[ch[x][0]]>mn[ch[x][1]]) dw=1,up=0;
else dw=0,up=1;
mn[x]=mn[ch[x][dw]];
cntmn[x]=cntmn[ch[x][dw]];
smn[x]=min(smn[ch[x][dw]],mn[ch[x][up]]);
}
}
void _build(int x,int l,int r){
mx[x]=smx[x]=-inf;
mn[x]=smn[x]=inf;
sumtag[x]=0;
sum[x]=0;
if (l==r){
sum[x]=mn[x]=mx[x]=a[l];
cntmx[x]=cntmn[x]=1;
return;
}
int mid=l+r>>1;
ch[x][0]=++tot; _build(ch[x][0],l,mid);
ch[x][1]=++tot; _build(ch[x][1],mid+1,r);
pushup(x);
}
void build(int _n){n=_n; tot=1; _build(1,1,n);}
void give_sumtag(int x,int delta,int len){
sumtag[x]+=delta;
sum[x]+=1LL*delta*len;
mn[x]+=delta; mx[x]+=delta;
if (smn[x]!=inf) smn[x]+=delta;
if (smx[x]!=-inf) smx[x]+=delta;
}
void give_mxtag(int x,int delta,int len){
sum[x]+=1LL*(delta-mn[x])*cntmn[x];
mn[x]=delta;
mx[x]=max(mx[x],delta);
if (mn[x]==mx[x]){
sum[x]=1LL*delta*len;
cntmx[x]=cntmn[x]=len;
smx[x]=-inf; smn[x]=inf;
}
else
smx[x]=max(smx[x],delta);
}
void give_mntag(int x,int delta,int len){
sum[x]+=1LL*(delta-mx[x])*cntmx[x];
mx[x]=delta;
mn[x]=min(mn[x],delta);
if (mx[x]==mn[x]){
sum[x]=1LL*delta*len;
cntmx[x]=cntmn[x]=len;
smx[x]=-inf; smn[x]=inf;
}
else
smn[x]=min(smn[x],delta);
}
void downtag(int x,int l,int r){
int mid=l+r>>1;
if (sumtag[x]){
if (ch[x][0]) give_sumtag(ch[x][0],sumtag[x],mid-l+1);
if (ch[x][1]) give_sumtag(ch[x][1],sumtag[x],r-mid);
sumtag[x]=0;
}
if (ch[x][0])
if (mn[ch[x][0]]<mn[x]&&mn[x]<smn[ch[x][0]])
give_mxtag(ch[x][0],mn[x],mid-l+1);
if (ch[x][1])
if (mn[ch[x][1]]<mn[x]&&mn[x]<smn[ch[x][1]])
give_mxtag(ch[x][1],mn[x],r-mid);
if (ch[x][0])
if (mx[ch[x][0]]>mx[x]&&mx[x]>smx[ch[x][0]])
give_mntag(ch[x][0],mx[x],mid-l+1);
if (ch[x][1])
if (mx[ch[x][1]]>mx[x]&&mx[x]>smx[ch[x][1]])
give_mntag(ch[x][1],mx[x],r-mid);
//if (l!=r) pushup(x);
}
void _add(int x,int l,int r,int lx,int rx,int delta){
if (l<=lx&&rx<=r){
give_sumtag(x,delta,rx-lx+1);
return;
}
downtag(x,lx,rx);
int mid=lx+rx>>1;
if (l<=mid) _add(ch[x][0],l,r,lx,mid,delta);
if (r>mid) _add(ch[x][1],l,r,mid+1,rx,delta);
pushup(x);
}
void add(int l,int r,int delta){_add(1,l,r,1,n,delta);}
void _update_mx(int x,int l,int r,int lx,int rx,int delta){
if (mn[x]>=delta) return;
if (l<=lx&&rx<=r&&delta<smn[x]){
give_mxtag(x,delta,rx-lx+1);
return;
}
downtag(x,lx,rx);
int mid=lx+rx>>1;
if (l<=mid) _update_mx(ch[x][0],l,r,lx,mid,delta);
if (r>mid) _update_mx(ch[x][1],l,r,mid+1,rx,delta);
pushup(x);
}
void update_mx(int l,int r,int delta){_update_mx(1,l,r,1,n,delta);}
void _update_mn(int x,int l,int r,int lx,int rx,int delta){
if (mx[x]<=delta) return;
if (l<=lx&&rx<=r&&delta>smx[x]){
give_mntag(x,delta,rx-lx+1);
return;
}
downtag(x,lx,rx);
int mid=lx+rx>>1;
if (l<=mid) _update_mn(ch[x][0],l,r,lx,mid,delta);
if (r>mid) _update_mn(ch[x][1],l,r,mid+1,rx,delta);
pushup(x);
}
void update_mn(int l,int r,int delta){_update_mn(1,l,r,1,n,delta);}
int _query_mx(int x,int l,int r,int lx,int rx){
if (l<=lx&&rx<=r) return mx[x];
downtag(x,lx,rx);
int mid=lx+rx>>1,ret=-inf;
if (l<=mid) ret=max(ret, _query_mx(ch[x][0],l,r,lx,mid));
if (r>mid) ret=max(ret,_query_mx(ch[x][1],l,r,mid+1,rx));
return ret;
//pushup(x);
}
int query_mx(int l,int r){return _query_mx(1,l,r,1,n);}
int _query_mn(int x,int l,int r,int lx,int rx){
if (l<=lx&&rx<=r) return mn[x];
downtag(x,lx,rx);
int mid=lx+rx>>1,ret=inf;
if (l<=mid) ret=min(ret,_query_mn(ch[x][0],l,r,lx,mid));
if (r>mid) ret=min(ret,_query_mn(ch[x][1],l,r,mid+1,rx));
return ret;
//pushup(x);
}
int query_mn(int l,int r){return _query_mn(1,l,r,1,n);}
ll _query_sum(int x,int l,int r,int lx,int rx){
if (l<=lx&&rx<=r) return sum[x];
downtag(x,lx,rx);
int mid=lx+rx>>1;
ll ret=0;
if (l<=mid) ret+=_query_sum(ch[x][0],l,r,lx,mid);
if (r>mid) ret+=_query_sum(ch[x][1],l,r,mid+1,rx);
return ret;
//pushup(x);
}
ll query_sum(int l,int r){return _query_sum(1,l,r,1,n);}
void debug(int x,int l,int r){
if (l==r) printf("%d ",sum[x]);
if (l==r) return;
downtag(x,l,r);
int mid=l+r>>1;
debug(ch[x][0],l,mid);
debug(ch[x][1],mid+1,r);
}
}/}}}/
int n,m;
ll ans;
void debug(){
/for (int i=1;i<=n;++i) {
//ll tmp=Seg::query_mx(i,i);
printf("%d ",tmp);
}/
Seg::debug(1,1,n);
printf("\n");
}
int main(){
ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
//freopen("a2.out","w",stdout);
endif
int op,l,r;
int delta;
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d",a+i);
Seg::build(n);
//debug();
scanf("%d",&m);
int Cnt=0;
for (int i=1;i<=m;++i){
scanf("%d%d%d",&op,&l,&r);
if (op<=3){
scanf("%d",&delta);
if (op==1)
Seg::add(l,r,delta);
else if (op==2)
Seg::update_mx(l,r,delta);
else
Seg::update_mn(l,r,delta);
}
else{
++Cnt;
//if (Cnt==17996||Cnt==18080||Cnt==18289) debug();
if (op==4)
ans=Seg::query_sum(l,r);
else if (op==5)
ans=Seg::query_mx(l,r);
else
ans=Seg::query_mn(l,r);
printf("%lld\n",ans);
}
debug();
}
}