Segment tree beats~

Segment tree beats!

旨在练习 吉老师线段树,并且存个板子~

#576 (Div. 2) D. Welfare State

区间取 m a x max max 的裸题,对于取 m a x max max 操作,维护最小值、次小值、最小值次数,通过加标记的方式就能维护 取 m a x max max 操作了;
区间取 m i n min min 的操作 与之类似。

#include<bits/stdc++.h>
using namespace std;

inline int qread(){
    int s=0,w=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-')w=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
    return (w==-1?-s:s);}

int n,m;
int a[200050];
struct node{
	int mi,smi,cnt,tag;
}tr[800050];
void pushup(int p){
	if(tr[2*p].mi<tr[2*p+1].mi){
		tr[p].mi=tr[2*p].mi;tr[p].cnt=tr[2*p].cnt;
		tr[p].smi=min(tr[2*p+1].mi,tr[2*p].smi);
	}else if(tr[2*p].mi>tr[2*p+1].mi){
		tr[p].mi=tr[2*p+1].mi;tr[p].cnt=tr[2*p+1].cnt;
		tr[p].smi=min(tr[2*p].mi,tr[2*p+1].smi);
	}else {
		tr[p].mi=tr[2*p].mi;tr[p].cnt=tr[2*p].cnt+tr[2*p+1].cnt;
		tr[p].smi=min(tr[2*p].smi,tr[2*p+1].smi);
	}
}
void build(int p,int l,int r){
	tr[p].tag=-1;
	if(l==r){
		tr[p].mi=a[l];
		tr[p].smi=1e9+7;
		tr[p].cnt=1;
		return;
	}
	int mid=l+r>>1;
	build(2*p,l,mid);
	build(2*p+1,mid+1,r);
	pushup(p);
}
void pushdown(int p){
	if(tr[p].tag==-1)return ;
	if(tr[p].tag>tr[2*p].mi){
		tr[2*p].mi=tr[2*p].tag=tr[p].tag;
	}
	if(tr[p].tag>tr[2*p+1].mi){
		tr[2*p+1].mi=tr[2*p+1].tag=tr[p].tag;
	}
	tr[p].tag=-1;
} 
void update(int p,int l,int r,int w){
	if(tr[p].mi>=w)return;
	if(tr[p].smi>w){
		tr[p].mi=tr[p].tag=w;
		return;
	}
	pushdown(p);
	int mid=l+r>>1;
	update(2*p,l,mid,w);update(2*p+1,mid+1,r,w);
	pushup(p);
}
void update1(int p,int l,int r,int x,int w){
	if(l==r){
		tr[p].mi=w;
		return;
	}
	int mid=l+r>>1;pushdown(p);
	if(x<=mid)update1(2*p,l,mid,x,w);
	else update1(2*p+1,mid+1,r,x,w);
	pushup(p);
}
int query(int p,int l,int r,int x){
	if(l==r)return tr[p].mi;
	int mid=l+r>>1;
	pushdown(p);
	if(x<=mid)return query(2*p,l,mid,x);
	else return query(2*p+1,mid+1,r,x); 
}
int main()
{
	n=qread();
	for(int i=1;i<=n;i++){
		a[i]=qread();
	}
	build(1,1,n);
	m=qread();
	for(int i=1;i<=m;i++){
		int op;
		op=qread();
		if(op==1){
			int a,b;
			a=qread();b=qread();
			update1(1,1,n,a,b);
		}else {
			int a;a=qread();
			update(1,1,n,a);
		}
	}
	for(int i=1;i<=n;i++){
		printf("%d ",query(1,1,n,i));
	}
	return 0;
}

UOJ #4695. 最假女选手

数组长度 n n n ,操作数 m m m 都为 5 e 5 5e5 5e5
五种操作:
1.给一个区间 [ L , R ] [L,R] [L,R] 加上一个数 x x x
2.把一个区间 [ L , R ] [L,R] [L,R] 里小于 x x x 的数变成 x x x
3.把一个区间 [ L , R ] [L,R] [L,R] 里大于 x x x 的数变成 x x x
4.求区间 [ L , R ] [L,R] [L,R] 的和
5.求区间 [ L , R ] [L,R] [L,R] 的最大值
6.求区间 [ L , R ] [L,R] [L,R] 的最小值

在区间取 m i n min min 、取 m a x max max的基础上,加上了区间加的操作:
分别维护最小值、最大值、其他值的加标记;
区间加操作 就是把三个标记都加;区间取 m i n min min 操作就是在最大值的加标记上修改;取 m a x max max同理。

两个注意点:
以最大值上的加减标记为例。下传这个标记时要判断子区间内是否包含最大值,如果不包含则应下传其他值的加减标记;
如果一个区间的值域很小(只有 1 1 1 2 2 2 个数),可能会发生一个值既是最大值又是次小值这种情况,也就是发生了数域的重叠。这种情况要特判,分辨到底该被哪个标记作用。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline int qread(){
    int s=0,w=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-')w=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
    return (w==-1?-s:s);}

const int INF=2e9;
int n,m;
int s[500050];
struct node{
	//最大值、次大值、最大值个数、最小值、次小值、最小值个数 
	int mx,smx,cmx,mi,smi,cmi;
	ll sum;
	//最小值、最大值、其他值的修改标记 
	int add1,add2,add3;
}tr[2000050];
#define ls (p<<1)
#define rs (p<<1|1)
void pushup(int p){
	tr[p].sum=tr[ls].sum+tr[rs].sum;
	if(tr[ls].mi==tr[rs].mi){
		tr[p].mi=tr[ls].mi;
		tr[p].smi=min(tr[ls].smi,tr[rs].smi);
		tr[p].cmi=tr[ls].cmi+tr[rs].cmi;
	}else if(tr[ls].mi<tr[rs].mi){
		tr[p].mi=tr[ls].mi;
		tr[p].smi=min(tr[ls].smi,tr[rs].mi);
		tr[p].cmi=tr[ls].cmi; 
	}else {
		tr[p].mi=tr[rs].mi;
		tr[p].smi=min(tr[ls].mi,tr[rs].smi);
		tr[p].cmi=tr[rs].cmi;
	}
	if(tr[ls].mx==tr[rs].mx){
		tr[p].mx=tr[ls].mx;
		tr[p].smx=max(tr[ls].smx,tr[rs].smx);
		tr[p].cmx=tr[ls].cmx+tr[rs].cmx; 
	}else if(tr[ls].mx>tr[rs].mx){
		tr[p].mx=tr[ls].mx;
		tr[p].smx=max(tr[ls].smx,tr[rs].mx);
		tr[p].cmx=tr[ls].cmx;
	}else {
		tr[p].mx=tr[rs].mx;
		tr[p].smx=max(tr[ls].mx,tr[rs].smx);
		tr[p].cmx=tr[rs].cmx;
	}
}
//对tr[p]的修改,k1、k2、k3 分别为最小值、最大值、其他值的标记 
void update(int p,int l,int r,int k1,int k2,int k3){
	if(tr[p].mi==tr[p].mx){
		//如果区间只有一种值,应该只作用最大值、最小值的加减标记 
		if(k1==k3)k1=k2;
		else k2=k1;
		tr[p].sum+=1LL*k1*tr[p].cmi;
	}else{
		tr[p].sum+=1LL*k1*tr[p].cmi+1LL*k2*tr[p].cmx+1LL*k3*(r-l+1-tr[p].cmi-tr[p].cmx);
	}
	//次小值为最大值,应被最大值标记作用 
	if(tr[p].smi==tr[p].mx)tr[p].smi+=k2;
	else if(tr[p].smi!=INF)tr[p].smi+=k3;//否则被其他值的标记作用
	
	if(tr[p].smx==tr[p].mi)tr[p].smx+=k1;
	else if(tr[p].smx!=INF)tr[p].smx+=k3; 
	
	tr[p].mi+=k1;tr[p].mx+=k2;
	tr[p].add1+=k1;tr[p].add2+=k2;tr[p].add3+=k3;
}
void pushdown(int p,int l,int r){
	int mi=min(tr[ls].mi,tr[rs].mi);
	int mx=max(tr[ls].mx,tr[rs].mx);
	int mid=l+r>>1;
	update(ls,l,mid,tr[ls].mi==mi?tr[p].add1:tr[p].add3,
		tr[ls].mx==mx?tr[p].add2:tr[p].add3,tr[p].add3);
	update(rs,mid+1,r,tr[rs].mi==mi?tr[p].add1:tr[p].add3,
		tr[rs].mx==mx?tr[p].add2:tr[p].add3,tr[p].add3);
	
	tr[p].add1=tr[p].add2=tr[p].add3=0;
}
void build(int p,int l,int r){
	tr[p].add1=tr[p].add2=tr[p].add3=0;
	if(l==r){
		tr[p].sum=tr[p].mi=tr[p].mx=s[l];
		tr[p].smi=INF;tr[p].smx=-INF;
		tr[p].cmi=tr[p].cmx=1;
		return;
	}
	int mid=l+r>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(p); 
}
void update1(int p,int l,int r,int x,int y,int w){
	if(x<=l&&r<=y){
		update(p,l,r,w,w,w);
		return;
	}
	int mid=l+r>>1;
	pushdown(p,l,r);
	if(x<=mid)update1(2*p,l,mid,x,y,w);
	if(mid<y)update1(2*p+1,mid+1,r,x,y,w);
	pushup(p);
}
void update2(int p,int l,int r,int x,int y,int w){
	if(tr[p].mi>=w)return;
	if(x<=l&&r<=y&&tr[p].smi>w){
		update(p,l,r,w-tr[p].mi,0,0);
		return;
	}
	pushdown(p,l,r);
	int mid=l+r>>1;
	if(x<=mid)update2(ls,l,mid,x,y,w);
	if(mid<y)update2(rs,mid+1,r,x,y,w);
	pushup(p);
}
void update3(int p,int l,int r,int x,int y,int w){
	if(tr[p].mx<=w)return;
	if(x<=l&&r<=y&&tr[p].smx<w){
		update(p,l,r,0,w-tr[p].mx,0);
		return;
	}
	int mid=l+r>>1;
	pushdown(p,l,r);
	if(x<=mid)update3(ls,l,mid,x,y,w);
	if(mid<y)update3(rs,mid+1,r,x,y,w);
	pushup(p);
}
ll query1(int p,int l,int r,int x,int y){
	if(x<=l&&r<=y)return tr[p].sum;
	int mid=l+r>>1;
	pushdown(p,l,r);
	ll ans=0;
	if(x<=mid)ans+=query1(ls,l,mid,x,y);
	if(mid<y)ans+=query1(rs,mid+1,r,x,y);
	return ans;
}
int query2(int p,int l,int r,int x,int y){
	if(x<=l&&r<=y)return tr[p].mx;
	int mid=l+r>>1,ans=-INF;
	pushdown(p,l,r);
	if(x<=mid)ans=max(ans,query2(ls,l,mid,x,y));
	if(mid<y)ans=max(ans,query2(rs,mid+1,r,x,y));
	return ans;
}
int query3(int p,int l,int r,int x,int y){
	if(x<=l&&r<=y)return tr[p].mi;
	int mid=l+r>>1,ans=INF;
	pushdown(p,l,r);
	if(x<=mid)ans=min(ans,query3(ls,l,mid,x,y));
	if(mid<y)ans=min(ans,query3(rs,mid+1,r,x,y));
	return ans; 
}
#undef ls
#undef rs
int main(){
	n=qread();
	for(int i=1;i<=n;i++)s[i]=qread();
	build(1,1,n);
	m=qread();
	while(m--){
		int op=qread(),l=qread(),r=qread();
		int x;
		if(op<=3)x=qread();
		if(op==1)update1(1,1,n,l,r,x);
		else if(op==2)update2(1,1,n,l,r,x);
		else if(op==3)update3(1,1,n,l,r,x);
		else if(op==4)printf("%lld\n",query1(1,1,n,l,r));
		else if(op==5)printf("%d\n",query2(1,1,n,l,r));
		else printf("%d\n",query3(1,1,n,l,r));
	}
	return 0;
}

#3064. Tyvj 1518 CPU监控

维护五个标记,区间加标记、区间赋值标记、区间历史最大加标记、区间历史最大赋值标记、是否有赋值标记。
这个标记是可以合并的,区间赋值之后加,直接加在赋值上即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline int qread(){
    int s=0,w=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-')w=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
    return (w==-1?-s:s);}
    
const int INF=2e9;
int n,m;
int s[100050];
struct node{
	//区间最大值、区间历史最大值 
	int mx,mx_;
	//区间加标记、区间覆盖标记、区间历史最大加标记、区间历史最大覆盖标记 
	int add,cov,add_,cov_;
	int tag;//是否被区间覆盖了 
}tr[400050];
#define ls p<<1
#define rs p<<1|1
#define mid (l+r>>1)
void pushup(int p){
	tr[p].mx=max(tr[ls].mx,tr[rs].mx);
	tr[p].mx_=max(tr[ls].mx_,tr[rs].mx_);
}
void plu(int p,int k1,int k2){
	tr[p].mx_=max(tr[p].mx_,tr[p].mx+k2);
	tr[p].mx+=k1;
	if(tr[p].tag){
		tr[p].cov_=max(tr[p].cov_,tr[p].cov+k2);
		tr[p].cov+=k1;
	}else{
		tr[p].add_=max(tr[p].add_,tr[p].add+k2);
		tr[p].add+=k1;
	}
}
void cov(int p,int k1,int k2){
	tr[p].mx_=max(tr[p].mx_,k2);
	tr[p].mx=k1;
	tr[p].cov_=max(tr[p].cov_,k2);
	tr[p].cov=k1;
	tr[p].tag=1;
}
void pushdown(int p){
	if(tr[p].add){
		plu(ls,tr[p].add,tr[p].add_);
		plu(rs,tr[p].add,tr[p].add_);
		tr[p].add=0;tr[p].add_=0;
	}
	if(tr[p].tag){
		cov(ls,tr[p].cov,tr[p].cov_);
		cov(rs,tr[p].cov,tr[p].cov_);
		tr[p].tag=0;tr[p].cov_=INT_MIN;
	}
}
void build(int p,int l,int r){
	tr[p].tag=0;tr[p].add=0;tr[p].add_=0;
	tr[p].cov_=INT_MIN;
	if(l==r){
		tr[p].mx=tr[p].mx_=s[l];
		return;
	}
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(p);
}
void update1(int p,int l,int r,int x,int y,int w){
	if(x<=l&&r<=y){
		plu(p,w,w);
		return;
	}
	pushdown(p);
	if(x<=mid)update1(ls,l,mid,x,y,w);
	if(mid<y)update1(rs,mid+1,r,x,y,w);
	pushup(p);
}
void update2(int p,int l,int r,int x,int y,int w){
	if(x<=l&&r<=y){
		cov(p,w,w);
		return;
	}
	pushdown(p);
	if(x<=mid)update2(ls,l,mid,x,y,w);
	if(mid<y)update2(rs,mid+1,r,x,y,w);
	pushup(p);
}
int query1(int p,int l,int r,int x,int y){
	if(x<=l&&r<=y)return tr[p].mx;
	pushdown(p);
	int ans=INT_MIN;
	if(x<=mid)ans=max(ans,query1(ls,l,mid,x,y));
	if(mid<y)ans=max(ans,query1(rs,mid+1,r,x,y));
	return ans;
} 
int query2(int p,int l,int r,int x,int y){
	if(x<=l&&r<=y)return tr[p].mx_;
	pushdown(p);
	int ans=INT_MIN;
	if(x<=mid)ans=max(ans,query2(ls,l,mid,x,y));
	if(mid<y)ans=max(ans,query2(rs,mid+1,r,x,y));
	return ans;
} 
#undef ls
#undef rs
#undef mid 
int main(){
	n=qread();
	for(int i=1;i<=n;i++)s[i]=qread();
	m=qread();
	build(1,1,n);
	for(int i=1;i<=m;i++){
		char ss[4];scanf("%s",ss);
		int a=qread(),b=qread();
		if(ss[0]=='Q'){
			printf("%d\n",query1(1,1,n,a,b));
		}else if(ss[0]=='A'){
			printf("%d\n",query2(1,1,n,a,b));
		}else if(ss[0]=='P'){
			int c=qread();
			update1(1,1,n,a,b,c);
		}else {
			int c=qread();
			update2(1,1,n,a,b,c);
		}
	}
	return 0;
}

#164. 【清华集训2015】V

给出 l,r,k,对于所有 i∈[l,r],将 A[i]加上k;
给出 l,r,k,对于所有 i∈[l,r],将 A[i]变成max(A[i]-k,0);
给出 l,r,k,对于所有 i∈[l,r],将 A[i]=k;
给出 p,询问 A[p]
给出 p,询问 B[p]

维护两个标记,先加再取 m a x max max,是可以合并的。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pll pair<ll,ll>
inline int qread(){
    int s=0,w=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-')w=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
    return (w==-1?-s:s);}
    
const ll INF=1e18;
int n,m;
int s[500050];
struct node{
	pll his,now;
}tr[2000050];
#define ls p<<1
#define rs p<<1|1
#define mid (l+r>>1)
pll merge(pll a,pll b){
	return make_pair(max(a.first+b.first,-INF),max(a.second+b.first,b.second));
}
pll getmx(pll a,pll b){
	return make_pair(max(a.first,b.first),max(a.second,b.second));
}
void update(int p,pll k1,pll k2){
	tr[p].his=getmx(tr[p].his,merge(tr[p].now,k2));
	tr[p].now=merge(tr[p].now,k1);
}
void pushdown(int p){
	update(ls,tr[p].now,tr[p].his);
	update(rs,tr[p].now,tr[p].his);
	tr[p].now=tr[p].his=make_pair(0,0);
}
void build(int p,int l,int r){
	tr[p].now=tr[p].his=make_pair(0,0);
	if(l==r){
		tr[p].now=tr[p].his=make_pair(s[l],0);
		return;
	}
	build(ls,l,mid);
	build(rs,mid+1,r);
}
void update1(int p,int l,int r,int x,int y,int w){
	if(x<=l&&r<=y){
		update(p,make_pair(w,0),make_pair(w,0));
		return;
	}
	pushdown(p);
	if(x<=mid)update1(ls,l,mid,x,y,w);
	if(mid<y)update1(rs,mid+1,r,x,y,w);
}
void update2(int p,int l,int r,int x,int y,int w){
	if(x<=l&&r<=y){
		update(p,make_pair(-w,0),make_pair(-w,0));
		return;
	}
	pushdown(p);
	if(x<=mid)update2(ls,l,mid,x,y,w);
	if(mid<y)update2(rs,mid+1,r,x,y,w);
}
void update3(int p,int l,int r,int x,int y,int w){
	if(x<=l&&r<=y){
		update(p,make_pair(-INF,w),make_pair(-INF,w));
		return;
	}
	pushdown(p);
	if(x<=mid)update3(ls,l,mid,x,y,w);
	if(mid<y)update3(rs,mid+1,r,x,y,w);
}
ll query1(int p,int l,int r,int x){
	if(l==r)return max(tr[p].now.first,tr[p].now.second);
	pushdown(p);
	if(x<=mid)return query1(ls,l,mid,x);
	else return query1(rs,mid+1,r,x); 
}
ll query2(int p,int l,int r,int x){
	if(l==r)return max(tr[p].his.first,tr[p].his.second);
	pushdown(p);
	if(x<=mid)return query2(ls,l,mid,x);
	else return query2(rs,mid+1,r,x); 
}

#undef ls
#undef rs
#undef mid 
int main(){
	n=qread(),m=qread();
	for(int i=1;i<=n;i++)s[i]=qread();
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int op=qread(),l=qread(),r;
		int x;
		if(op<=3)r=qread(),x=qread();
		if(op==1){
			update1(1,1,n,l,r,x);
		}else if(op==2){
			update2(1,1,n,l,r,x);
		}else if(op==3){
			update3(1,1,n,l,r,x);
		}else if(op==4){
			printf("%lld\n",query1(1,1,n,l));
		}else printf("%lld\n",query2(1,1,n,l));
	}
	return 0;
}

#169. 【UR #11】元旦老人与数列

给出一个长度为 n=5e5 的序列A,定义辅助数组 B,初始时与 A完全相同。给出 m=5e5 次操作,每次操作为以下四种类型之一:
1、给出 l,r,k,对于所有 i∈[l,r],将 A[i]加上 k;
2、给出 l,r,k,对于所有 i∈[l,r],将 A[i]=max(A[i],k);
3、给出 l,r,求序列 A 区间 [l,r] 的最小值;
4、给出 l,r,求序列 B 区间 [l,r] 的最小值。
每次操作后,对于所有 i,将 B[i]=min(B[i],A[i]);

通过数域划分,维护最小值得加标记、其他值得加标记、最小值的历史最小加标记、其他值的历史最小加标记 可以在 O ( m l o g 2 n ) O(mlog^2n) O(mlog2n) 完成

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pll pair<ll,ll>
inline int qread(){
    int s=0,w=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-')w=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
    return (w==-1?-s:s);}
    
const int INF=2e9;
int n,m;
int s[500050];
struct node{
	int mi,smi,add1,add2,mi_;
	int add1_,add2_;
}tr[2000050];
#define ls p<<1
#define rs p<<1|1
#define mid (l+r>>1)
void pushup(int p){
	tr[p].mi_=min(tr[ls].mi_,tr[rs].mi_);
	if(tr[ls].mi==tr[rs].mi){
		tr[p].mi=tr[ls].mi;
		tr[p].smi=min(tr[ls].smi,tr[rs].smi);
	}else if(tr[ls].mi<tr[rs].mi){
		tr[p].mi=tr[ls].mi;
		tr[p].smi=min(tr[ls].smi,tr[rs].mi);
	}else {
		tr[p].mi=tr[rs].mi;
		tr[p].smi=min(tr[ls].mi,tr[rs].smi);
	}
}
void update(int p,int k1,int k1_,int k2,int k2_){
	tr[p].mi_=min(tr[p].mi_,tr[p].mi+k1_);
	tr[p].mi=tr[p].mi+k1;
	tr[p].add1_=min(tr[p].add1_,tr[p].add1+k1_);
	tr[p].add1+=k1;
	if(tr[p].smi!=INF)
		tr[p].smi+=k2,tr[p].add2_=min(tr[p].add2_,tr[p].add2+k2_),tr[p].add2+=k2;
}
void pushdown(int p){
	int mi=min(tr[ls].mi,tr[rs].mi);
	if(tr[ls].mi==mi)update(ls,tr[p].add1,tr[p].add1_,tr[p].add2,tr[p].add2_);
	else update(ls,tr[p].add2,tr[p].add2_,tr[p].add2,tr[p].add2_);
	if(tr[rs].mi==mi)update(rs,tr[p].add1,tr[p].add1_,tr[p].add2,tr[p].add2_);
	else update(rs,tr[p].add2,tr[p].add2_,tr[p].add2,tr[p].add2_); 
	tr[p].add1=tr[p].add1_=tr[p].add2=tr[p].add2_=0;
}
void build(int p,int l,int r){
	tr[p].add1=tr[p].add1_=tr[p].add2=tr[p].add2_=0;
	if(l==r){
		tr[p].mi=tr[p].mi_=s[l];
		tr[p].smi=INF;
		return ;
	}
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(p);
}
void update1(int p,int l,int r,int x,int y,int w){
	if(x<=l&&r<=y){
		update(p,w,w,w,w);
		return;
	}
	pushdown(p);
	if(x<=mid)update1(ls,l,mid,x,y,w);
	if(mid<y)update1(rs,mid+1,r,x,y,w);
	pushup(p);
}
void update2(int p,int l,int r,int x,int y,int w){
	if(tr[p].mi>=w)return;
	if(x<=l&&r<=y&&tr[p].smi>w){
		update(p,w-tr[p].mi,w-tr[p].mi,0,0);
		return;
	} 
	pushdown(p);
	if(x<=mid)update2(ls,l,mid,x,y,w);
	if(mid<y)update2(rs,mid+1,r,x,y,w);
	pushup(p);
}
int query1(int p,int l,int r,int x,int y){
	if(x<=l&&r<=y)return tr[p].mi;
	int ans=INF;
	pushdown(p);
	if(x<=mid)ans=min(ans,query1(ls,l,mid,x,y));
	if(mid<y)ans=min(ans,query1(rs,mid+1,r,x,y));
	return ans;
}
int query2(int p,int l,int r,int x,int y){
	if(x<=l&&r<=y)return tr[p].mi_;
	int ans=INF;
	pushdown(p);
	if(x<=mid)ans=min(ans,query2(ls,l,mid,x,y));
	if(mid<y)ans=min(ans,query2(rs,mid+1,r,x,y));
	return ans;
}
#undef ls
#undef rs
#undef mid 
int main(){
	n=qread(),m=qread();
	for(int i=1;i<=n;i++)s[i]=qread();
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int op=qread(),l=qread(),r=qread();
		int x;
		if(op<=2)x=qread();
		if(op==1)update1(1,1,n,l,r,x);
		else if(op==2)update2(1,1,n,l,r,x);
		else if(op==3)printf("%d\n",query1(1,1,n,l,r));
		else if(op==4)printf("%d\n",query2(1,1,n,l,r));
	}
	
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值