区间取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]+=1LLdeltalen;
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]=1LLdeltalen;
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]=1LLdeltalen;
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 (lr) 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 (op1)
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 (Cnt17996||Cnt18080||Cnt18289) 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();
}
}

posted @ 2018-12-19 16:20  yoyoball  阅读(519)  评论(0)    收藏  举报