区间取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();
}

}

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