题解: 看到这个题想的直接最大最小 次大次小 已经最大最小值出现的次数 和 求和 第一次做的时候 维护了最大值和最小值改变的下传标记 但是没有处理好与区间加标记的先后顺序 后来看了别人的题解 发现不用维护最值下传标记 因为可以通过判断其儿子的最值是否发生改变 然后用父亲的最值去更新即可 然后就只用维护区间加的标记 就行了
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=5e5+10;
const double eps=1e-8;
#define ll long long
const int inf=1e9;
using namespace std;
struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
return x*f;
}
typedef struct node{
int mx,cmx,numx;
int mn,cmn,numn;
ll sum,flag;
}node;
node d[MAXN<<2];
int a[MAXN];
void up(int rt){
d[rt].sum=d[rt<<1].sum+d[rt<<1|1].sum;
d[rt].numx=d[rt].numn=0;
d[rt].mx=max(d[rt<<1].mx,d[rt<<1|1].mx);
if(d[rt].mx==d[rt<<1].mx)d[rt].numx+=d[rt<<1].numx;
if(d[rt].mx==d[rt<<1|1].mx)d[rt].numx+=d[rt<<1|1].numx;
d[rt].cmx=max(d[rt<<1].cmx,d[rt<<1|1].cmx);
if(d[rt<<1].mx!=d[rt<<1|1].mx)d[rt].cmx=max(d[rt].cmx,min(d[rt<<1].mx,d[rt<<1|1].mx));
d[rt].mn=min(d[rt<<1].mn,d[rt<<1|1].mn);
if(d[rt].mn==d[rt<<1].mn)d[rt].numn+=d[rt<<1].numn;
if(d[rt].mn==d[rt<<1|1].mn)d[rt].numn+=d[rt<<1|1].numn;
d[rt].cmn=min(d[rt<<1].cmn,d[rt<<1|1].cmn);
if(d[rt<<1].mn!=d[rt<<1|1].mn)d[rt].cmn=min(d[rt].cmn,max(d[rt<<1].mn,d[rt<<1|1].mn));
}
void push2(int x,int k){
if(d[x].mn==d[x].cmx)d[x].cmx=k;
if(d[x].cmx==-inf&&d[x].cmn==inf)d[x].mx=k;
d[x].sum+=1ll*(k-d[x].mn)*d[x].numn,d[x].mn=k;
}
void push3(int x,int k){
if(d[x].mx==d[x].cmn)d[x].cmn=k;
if(d[x].cmx==-inf&&d[x].cmn==inf)d[x].mn=k;
d[x].sum-=1ll*(d[x].mx-k)*d[x].numx,d[x].mx=k;
}
void push(int x,int l,int r){
if(d[x].flag){
int mid=(l+r)>>1;
d[x<<1].flag+=d[x].flag;d[x<<1].mx+=d[x].flag;d[x<<1].mn+=d[x].flag;d[x<<1].sum+=1ll*(mid-l+1)*d[x].flag;
if(d[x<<1].cmx!=-inf&&d[x<<1].cmn!=inf)d[x<<1].cmx+=d[x].flag,d[x<<1].cmn+=d[x].flag;
d[x<<1|1].flag+=d[x].flag;d[x<<1|1].mx+=d[x].flag;d[x<<1|1].mn+=d[x].flag;d[x<<1|1].sum+=1ll*(r-mid)*d[x].flag;
if(d[x<<1|1].cmx!=-inf&&d[x<<1|1].cmn!=inf)d[x<<1|1].cmx+=d[x].flag,d[x<<1|1].cmn+=d[x].flag;
d[x].flag=0;
}
//cout<<l<<"-----==="<<r<<" "<<d[x<<1|1].mn<<" "<<d[x<<1|1].cmn<<" "<<d[x].mn<<" "<<d[x<<1|1].flag<<endl;
if(d[x<<1].cmx<d[x].mx&&d[x].mx<d[x<<1].mx)push3(x<<1,d[x].mx);
if(d[x<<1|1].cmx<d[x].mx&&d[x].mx<d[x<<1|1].mx)push3(x<<1|1,d[x].mx);
if(d[x<<1].mn<d[x].mn&&d[x].mn<d[x<<1].cmn)push2(x<<1,d[x].mn);
if(d[x<<1|1].mn<d[x].mn&&d[x].mn<d[x<<1|1].cmn)push2(x<<1|1,d[x].mn);
}
void built(int rt,int l,int r){
d[rt].flag=0;
if(l==r){
d[rt].mn=d[rt].mx=d[rt].sum=a[l];
d[rt].numn=d[rt].numx=1;
d[rt].cmx=-inf;d[rt].cmn=inf;
return ;
}
int mid=(l+r)>>1;
built(rt<<1,l,mid);
built(rt<<1|1,mid+1,r);
up(rt);
}
void operator1(int rt,int l,int r,int ql,int qr,ll x){
if(ql<=l&&r<=qr){
d[rt].mn+=x;d[rt].mx+=x;d[rt].sum+=1ll*(r-l+1)*x;
if(d[rt].cmx!=-inf&&d[rt].cmn!=inf)d[rt].cmx+=x,d[rt].cmn+=x;
d[rt].flag+=x;
return ;
}
int mid=(l+r)>>1;
push(rt,l,r);
if(ql<=mid)operator1(rt<<1,l,mid,ql,qr,x);
if(qr>mid)operator1(rt<<1|1,mid+1,r,ql,qr,x);
up(rt);
// cout<<l<<"====="<<r<<" "<<d[rt].mx<<" "<<d[rt].cmx<<" "<<d[rt].mn<<" "<<d[rt].cmn<<" "<<d[rt].sum<<endl;
//cout<<l<<":::::"<<mid<<endl;
//cout<<l<<"====="<<mid<<" "<<d[rt<<1].mx<<" "<<d[rt<<1].cmx<<" "<<d[rt<<1].mn<<" "<<d[rt<<1].cmn<<" "<<d[rt<<1].sum<<" "<<d[rt<<1].flag<<endl;
}
void operator2(int rt,int l,int r,int ql,int qr,int x){
if(ql<=l&&r<=qr){
if(d[rt].mn>=x)return ;
else if(d[rt].cmn>x){
if(d[rt].mn==d[rt].cmx)d[rt].cmx=x;
if(d[rt].cmx==-inf&&d[rt].cmn==inf)d[rt].mx=x;
d[rt].sum+=1ll*(x-d[rt].mn)*d[rt].numn,d[rt].mn=x;
return ;
}
}
int mid=(l+r)>>1;
push(rt,l,r);
if(ql<=mid)operator2(rt<<1,l,mid,ql,qr,x);
if(qr>mid)operator2(rt<<1|1,mid+1,r,ql,qr,x);
up(rt);
// cout<<l<<":::"<<r<<" "<<d[rt].mx<<" "<<d[rt].cmx<<" "<<d[rt].mn<<" "<<d[rt].cmn<<" "<<d[rt].sum<<endl;
// cout<<l<<":::"<<mid<<" "<<d[rt<<1].mx<<" "<<d[rt<<1].cmx<<" "<<d[rt<<1].mn<<" "<<d[rt<<1].cmn<<" "<<d[rt<<1].sum<<endl;
// cout<<mid+1<<":::"<<r<<" "<<d[rt<<1|1].mx<<" "<<d[rt<<1|1].cmx<<" "<<d[rt<<1|1].mn<<" "<<d[rt<<1|1].cmn<<" "<<d[rt<<1|1].sum<<endl;
}
void operator3(int rt,int l,int r,int ql,int qr,int x){
if(ql<=l&&r<=qr){
if(d[rt].mx<=x)return ;
else if(d[rt].cmx<x){
if(d[rt].mx==d[rt].cmn)d[rt].cmn=x;
if(d[rt].cmx==-inf&&d[rt].cmn==inf)d[rt].mn=x;
d[rt].sum-=1ll*(d[rt].mx-x)*d[rt].numx,d[rt].mx=x;
return ;
}
}
int mid=(l+r)>>1;
push(rt,l,r);
if(ql<=mid)operator3(rt<<1,l,mid,ql,qr,x);
if(qr>mid)operator3(rt<<1|1,mid+1,r,ql,qr,x);
up(rt);
// cout<<"sb:::"<<endl;
//cout<<l<<":::"<<r<<" "<<d[rt].mx<<" "<<d[rt].cmx<<" "<<d[rt].mn<<" "<<d[rt].cmn<<" "<<d[rt<<1].sum<<" "<<d[rt<<1|1].sum<<endl;
}
ll ans;
void operator4(int rt,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr){ans+=d[rt].sum;return ;}
int mid=(l+r)>>1;
push(rt,l,r);
if(ql<=mid)operator4(rt<<1,l,mid,ql,qr);
if(qr>mid)operator4(rt<<1|1,mid+1,r,ql,qr);
up(rt);
}
void operator5(int rt,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr){ans=max(1ll*d[rt].mx,ans);return ;}
int mid=(l+r)>>1;
//cout<<l<<"::::"<<r<<" "<<d[rt<<1].mx<<" "<<d[rt<<1|1].mx<<endl;
push(rt,l,r);
// cout<<l<<"===="<<r<<" "<<d[rt<<1].mx<<" "<<d[rt<<1|1].mx<<endl;
if(ql<=mid)operator5(rt<<1,l,mid,ql,qr);
if(qr>mid)operator5(rt<<1|1,mid+1,r,ql,qr);
up(rt);
}
void operator6(int rt,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr){ans=min(ans,1ll*d[rt].mn);return ;}
int mid=(l+r)>>1;
// cout<<l<<"-----"<<r<<" "<<d[rt<<1].mn<<" "<<d[rt<<1|1].mn<<endl;
push(rt,l,r);
// cout<<l<<"====="<<r<<" "<<d[rt<<1].mn<<" "<<d[rt<<1|1].mn<<endl;
if(ql<=mid)operator6(rt<<1,l,mid,ql,qr);
if(qr>mid)operator6(rt<<1|1,mid+1,r,ql,qr);
up(rt);
}
int main(){
int n=read();
inc(i,1,n)a[i]=read();
built(1,1,n);
int m=read();
int op,l,r;ll x;
while(m--){
op=read();l=read();r=read();
if(op==1)x=read(),operator1(1,1,n,l,r,x);
else if(op==2)x=read(),operator2(1,1,n,l,r,x);
else if(op==3)x=read(),operator3(1,1,n,l,r,x);
else if(op==4)ans=0,operator4(1,1,n,l,r),printf("%lld\n",ans);
else if(op==5)ans=-inf,operator5(1,1,n,l,r),printf("%lld\n",ans);
else ans=inf,operator6(1,1,n,l,r),printf("%lld\n",ans);
}
return 0;
}
第一行一个整数 N表示序列长度。
第二行N 个整数Ai 表示初始序列。
第三行一个整数M 表示操作个数。
接下来M 行,每行三或四个整数,第一个整数Tp 表示操作类型,接下来L,R,X 或L,R 表述操作数。
1<=tp<=6,N,M<=5*10^5,|Ai|<=10^8
Tp=1时,|x|<=1000
Tp=2或3时,|x|<=10^8