本题要求:
1.区间对\(x\)取 min
2.区间和
3.区间 min
只是吉司机线段树板子题。
即我们维护\(max,smax,cnt\),最大值和次大值,最大值的个数。
在往下过程中,当且仅当\(max > p > smax\)时进行操作。
那么我们很容易的统计。
#include<iostream>
#include<cstdio>
#define ll long long
#define N 1000006
struct P{
int mx,mx2,cmx,tag;
ll s;
}e[N << 2];
int num[N];
inline int read(){
int ans = 0;
char a = getchar();
while(! (a <= '9' && a >= '0')) a = getchar();
while(a <= '9' && a >= '0')
ans = (ans << 3) + (ans << 1) + (a - '0'),a = getchar();
return ans;
}
#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
#define mid ((l + r) >> 1)
#define root 1,1,n
#define mx(x) e[x].mx
#define mx2(x) e[x].mx2
#define cnt(x) e[x].cmx
#define t(x) e[x].tag
#define s(x) e[x].s
#define INF (0x7fffffff)
inline void up(int u){
if(mx(ls(u)) < mx(rs(u))){
mx(u) = mx(rs(u));
cnt(u) = cnt(rs(u));
mx2(u) = std::max(mx(ls(u)),mx2(rs(u)));
}else{
if(mx(ls(u)) > mx(rs(u))){
mx(u) = mx(ls(u));
cnt(u) = cnt(ls(u));
mx2(u) = std::max(mx(rs(u)),mx2(ls(u)));
}else{
mx(u) = mx(ls(u));
cnt(u) = cnt(ls(u)) + cnt(rs(u));
mx2(u) = std::max(mx2(rs(u)),mx2(ls(u)));
}
}
s(u) = s(ls(u)) + s(rs(u));
}
inline void build (int u,int l,int r){
t(u) = -1;
if(l == r){
mx(u) = num[l];
mx2(u) = t(u) = - 1;
cnt(u) = 1;
s(u) = num[l];
return ;
}
build(ls(u),l,mid);
build(rs(u),mid + 1,r);
up(u);
}
inline void del(int u,ll tg){
if(mx(u) <= tg){
return ;
}
s(u) += (1ll * tg - mx(u)) * cnt(u);
mx(u) = t(u) = tg;
}
inline void down(int u){
if(t(u) == -1)return ;
del(ls(u),t(u)),del(rs(u),t(u));
t(u) = -1;
}
inline void modi(int u,int l,int r,int tl,int tr,ll p){
if(mx(u) <= p)return ;
if(tl <= l && r <= tr && mx2(u) < p){
del(u,p);
return;
}
down(u);
if(tl <= mid)modi(ls(u),l,mid,tl,tr,p);
if(tr > mid)modi(rs(u),mid + 1,r,tl,tr,p);
up(u);
}
inline ll q(int u,int l,int r,int tl,int tr){
if(tl <= l && r <= tr)
return s(u);
down(u);
ll ans = 0;
if(tl <= mid)
ans = ans + q(ls(u),l,mid,tl,tr);
if(tr > mid)
ans = ans + q(rs(u),mid + 1,r,tl,tr);
return ans;
}
inline ll q2(int u,int l,int r,int tl,int tr){
if(tl <= l && r <= tr)
return mx(u);
down(u);
ll ans = 0;
if(tl <= mid)
ans = std::max(ans,q2(ls(u),l,mid,tl,tr));
if(tr > mid)
ans = std::max(ans,q2(rs(u),mid + 1,r,tl,tr));
return ans;
}
inline void solve(){
int n,m;
n = read(),m = read();
for(int i = 1;i <= n;++i)
num[i] = read();
build(root);
while(m -- ){
int op,l,r;
op = read(),l = read(),r = read();
if(op == 0){
int z;
z = read();
modi(root,l,r,z);
}else{
if(op == 2)
std::cout<<q(root,l,r)<<std::endl;
else
std::cout<<q2(root,l,r)<<std::endl;
}
}
}
int main(){
ll t;
scanf("%lld",&t);
while(t -- ){
solve();
}
}