重载了Num 类型的运算
max 包含 最大值,次大值,最大值个数
min 包含 最小值,次小值,最小值个数
代码如下 :
#include<bits/stdc++.h>
#define ll long long
#define MX LLONG_MAX
#define MN LLONG_MIN
using namespace std;
const int N=5e5+5;
template <class T>
inline void read(T &res){
char c;bool f=0;
while(!isdigit(c=getchar())) if(c=='-') f=1;
res=(c^48);
while(isdigit(c=getchar())) res=(res<<1)+(res<<3)+(c^48);
if(f) res=~res+1;
}
int n,m,a[N];
#define ls (u<<1)
#define rs (u<<1|1)
#define mid (l+r>>1)
struct Num{
ll num,se,count;
Num operator + (const ll& x) const {return (Num){num+x,se+x,count}; }
friend Num max(Num x,Num y){
ll a,b,c;
if(x.num==y.num){
a=x.num;
if(x.se>y.se) b=x.se;
else b=y.se;
c=x.count+y.count;
}
else if(x.num>y.num){
a=x.num;
if(x.se>y.num) b=x.se;
else b=y.num;
c=x.count;
}
else{
a=y.num;
if(x.num>y.se) b=x.num;
else b=y.se;
c=y.count;
}
return (Num){a,b,c};
}
friend Num min(Num x,Num y){
ll a,b,c;
if(x.num==y.num){
a=x.num;
if(x.se<y.se) b=x.se;
else b=y.se;
c=x.count+y.count;
}
else if(x.num<y.num){
a=x.num;
if(x.se<y.num) b=x.se;
else b=y.num;
c=x.count;
}
else{
a=y.num;
if(x.num<y.se) b=x.num;
else b=y.se;
c=y.count;
}
return (Num){a,b,c};
}
};
struct SegTree{
struct Tree{
Num max,min;
ll sum,tag,tag_min,tag_max;
}t[N<<2];
void push_up(int u,int l,int r){
t[u].sum=t[ls].sum+t[rs].sum;
t[u].max=max(t[ls].max,t[rs].max);
t[u].min=min(t[ls].min,t[rs].min);
}
void build(int u,int l,int r){
t[u].tag_min=MX; t[u].tag_max=MN;
if(l==r){
t[u].sum=a[l]; t[u].max=(Num){a[l],MN,1}; t[u].min=(Num){a[l],MX,1};
return ;
}
build(ls,l,mid), build(rs,mid+1,r);
push_up(u,l,r);
}
void Print(int u,int l,int r){
printf("rt:%d -> [%d,%d] -- Sum:%lld ---Max <- ",u,l,r,t[u].sum);
printf("(Num){%lld,%lld,%lld}\n",t[u].max.num,t[u].max.se,t[u].max.count);
if(l==r) return ;
Print(ls,l,mid), Print(rs,mid+1,r);
}
void add(int u,int l,int r,ll x){ t[u].sum+=(r-l+1)*x; t[u].max=t[u].max+x; t[u].min=t[u].min+x; t[u].tag+=x;}
void Min(int u,int l,int r,int x){
if(t[u].max.num<=x) return ;
else if(t[u].max.se<x){
t[u].tag_min=x;
t[u].sum-=(t[u].max.num-x)*t[u].max.count;
t[u].max.num=x;
}
else{
Min(ls,l,mid,x), Min(rs,mid+1,r,x);
push_up(u,l,r);
}
}
void Max(int u,int l,int r,int x){
if(t[u].min.num>=x) return ;
else if(t[u].min.se>x){
t[u].tag_max=x;
t[u].sum+=(x-t[u].min.num)*t[u].min.count;
t[u].min.num=x;
}
else{
Max(ls,l,mid,x), Max(rs,mid+1,r,x);
push_up(u,l,r);
}
}
void push_down(int u,int l,int r){
if(t[u].tag){
add(ls,l,mid,t[u].tag), add(rs,mid+1,r,t[u].tag);
t[u].tag=0;
}
if(t[u].tag_min!=MX){
Min(ls,l,mid,t[u].tag_min), Min(rs,mid+1,r,t[u].tag_min);
t[u].tag_min=MX;
}
if(t[u].tag_max!=MN){
Max(ls,l,mid,t[u].tag_max), Max(rs,mid+1,r,t[u].tag_max);
t[u].tag_max=MN;
}
}
void modify(int u,int l,int r,int ql,int qr,int x){
if(l>qr||r<ql) return ;
if(ql<=l&&r<=qr) return add(u,l,r,x);
push_down(u,l,r);
modify(ls,l,mid,ql,qr,x), modify(rs,mid+1,r,ql,qr,x);
push_up(u,l,r);
}
void modify_min(int u,int l,int r,int ql,int qr,int x){
if(l>qr||r<ql) return ;
if(ql<=l&&r<=qr) return Min(u,l,r,x);
push_down(u,l,r);
modify_min(ls,l,mid,ql,qr,x), modify_min(rs,mid+1,r,ql,qr,x);
push_up(u,l,r);
}
void modify_max(int u,int l,int r,int ql,int qr,int x){
if(l>qr||r<ql) return ;
if(ql<=l&&r<=qr) return Max(u,l,r,x);
push_down(u,l,r);
modify_max(ls,l,mid,ql,qr,x), modify_max(rs,mid+1,r,ql,qr,x);
push_up(u,l,r);
}
ll query_sum(int u,int l,int r,int ql,int qr){
if(l>qr||r<ql) return 0;
if(ql<=l&&r<=qr) return t[u].sum;
push_down(u,l,r);
return query_sum(ls,l,mid,ql,qr)+query_sum(rs,mid+1,r,ql,qr);
}
ll query_max(int u,int l,int r,int ql,int qr){
if(l>qr||r<ql) return MN;
if(ql<=l&&r<=qr) return t[u].max.num;
push_down(u,l,r);
return max(query_max(ls,l,mid,ql,qr),query_max(rs,mid+1,r,ql,qr));
}
ll query_min(int u,int l,int r,int ql,int qr){
if(l>qr||r<ql) return MX;
if(ql<=l&&r<=qr) return t[u].min.num;
push_down(u,l,r);
return min(query_min(ls,l,mid,ql,qr),query_min(rs,mid+1,r,ql,qr));
}
}seg;
int main(){
read(n);
for(int i=1;i<=n;i++) read(a[i]);
read(m); seg.build(1,1,n);
for(int i=1,op,l,r,x;i<=m;i++){
read(op); read(l),read(r);
if(op==1){
read(x); seg.modify(1,1,n,l,r,x);
}
if(op==2){
read(x); seg.modify_max(1,1,n,l,r,x);
}
if(op==3){
read(x); seg.modify_min(1,1,n,l,r,x);
}
if(op==4){
cout<<seg.query_sum(1,1,n,l,r)<<"\n";
}
if(op==5){
cout<<seg.query_max(1,1,n,l,r)<<"\n";
}
if(op==6){
cout<<seg.query_min(1,1,n,l,r)<<"\n";
}
// seg.Print(1,1,n); cout<<"\n\n";
}
return 0;
}