国阳历0pts听取WA声一片吉司机线段树求调,玄关
查看原帖
国阳历0pts听取WA声一片吉司机线段树求调,玄关
877101
tianyk楼主2024/10/30 15:53

rt,代码如下

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
const long long inf=1e18;
struct node{
    long long sum,minn,maxx,smin,smax,cmax,cmin;
    //sum为区间和 minn为区间最小值 maxx为区间最大值 smin为区间严格次小值(不存在是为正无穷) smax为区间严格次大值(不存在是为负无穷) cmax为区间最大值数量 cmin为区间最小值数量 
    friend node operator + (node a,node b){
        node c;
        c.sum=a.sum+b.sum;
        c.minn=min(a.minn,b.minn);
        c.maxx=max(a.maxx,b.maxx);
        if(a.minn<b.minn){
            c.cmin=a.cmin;
            c.smin=min(a.smin,b.minn);
        }
        else if(a.minn>b.minn){
            c.cmin=b.cmin;
            c.smin=min(a.minn,b.smin);
        }
        else{
            c.cmin=a.cmin+b.cmin;
            c.smin=min(a.smin,b.smin);
        }
        if(a.maxx>b.maxx){
            c.cmax=a.cmax;
            c.smax=max(a.smax,b.maxx);
        }
        else if(a.maxx<b.maxx){
            c.cmax=b.cmax;
            c.smax=min(a.maxx,b.smax);
        }
        else{
            c.cmax=a.cmax+b.cmax;
            c.smax=min(a.smax,b.smax);
        }
        return c;
    }
}tree[N<<2];
long long maxt[N<<2],mint[N<<2],ot[N<<2],a[N];
//maxt[]为最大值的懒标记 mint[]为最小值的懒标记 ot[]为除最大值和最小值外的懒标记
void pushup(int rt){
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void build(long long l,long long r,int rt){
    if(l==r){
        tree[rt]={a[l],a[l],a[l],inf,-inf,1,1};
        return ;
    }
    long long mid=l+r>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    pushup(rt);
}
void lazy(long long len,int rt,long long maxtag,long long mintag,long long othertag){
    tree[rt].sum+=tree[rt].cmax*maxtag+tree[rt].cmin*mintag+max(0ll,(len-tree[rt].cmax-tree[rt].cmin))*othertag;
    if(tree[rt].maxx==tree[rt].minn)//整个区间值相同
        tree[rt].maxx=tree[rt].minn=tree[rt].maxx+maxtag+mintag;
    else if(tree[rt].maxx==tree[rt].smin){//整个区间只有两种值(最大值和最小值)
        tree[rt].maxx=tree[rt].smin=tree[rt].maxx+maxtag;
        tree[rt].minn=tree[rt].smax=tree[rt].minn+mintag;
    }
    else{//其余情况
        tree[rt].maxx+=maxtag,tree[rt].minn+=mintag;
        if(tree[rt].smax!=-inf)
            tree[rt].smax+=othertag;
        if(tree[rt].smin!=inf)
            tree[rt].smin+=othertag;
    }
    maxt[rt]+=maxtag,mint[rt]+=mintag,ot[rt]+=othertag;
}
void pushdown(long long l,long long r,int rt){
    if(maxt[rt]||mint[rt]||ot[rt]){
        long long mid=l+r>>1;
        long long maxx=max(tree[rt<<1].maxx,tree[rt<<1|1].maxx),minn=min(tree[rt<<1].minn,tree[rt<<1|1].minn);
        if(tree[rt<<1].maxx==maxx&&tree[rt<<1].minn==minn)
            lazy(mid-l+1,rt<<1,maxt[rt],mint[rt],ot[rt]);
        else if(tree[rt<<1].maxx==maxx)
            lazy(mid-l+1,rt<<1,maxt[rt],ot[rt],ot[rt]);
        else if(tree[rt<<1].minn==minn)
            lazy(mid-l+1,rt<<1,ot[rt],mint[rt],ot[rt]);
        else    
            lazy(mid-l+1,rt<<1,ot[rt],ot[rt],ot[rt]);
        if(tree[rt<<1|1].maxx==maxx&&tree[rt<<1|1].minn==minn)
            lazy(r-mid,rt<<1|1,maxt[rt],mint[rt],ot[rt]);
        else if(tree[rt<<1|1].maxx==maxx)
            lazy(r-mid,rt<<1|1,maxt[rt],ot[rt],ot[rt]);
        else if(tree[rt<<1|1].minn==minn)
            lazy(r-mid,rt<<1|1,ot[rt],mint[rt],ot[rt]);
        else    
            lazy(r-mid,rt<<1|1,ot[rt],ot[rt],ot[rt]);
        maxt[rt]=mint[rt]=ot[rt]=0;
    }
}
void updateadd(long long l,long long r,int rt,int L,int R,long long c){
    if(L<=l&&r<=R){
        lazy(r-l+1,rt,c,c,c);
        return ;
    }
    pushdown(l,r,rt);
    long long mid=l+r>>1;
    if(L<=mid)
        updateadd(l,mid,rt<<1,L,R,c);
    if(R>mid)
        updateadd(mid+1,r,rt<<1|1,L,R,c);
    pushup(rt);
}
void updatemax(long long l,long long r,int rt,int L,int R,long long c){
    if(tree[rt].minn>=c)
        return ;
    if(L<=l&&r<=R&&tree[rt].smin>=c){
        lazy(r-l+1,rt,0,c-tree[rt].minn,0);
        return ;
    }
    pushdown(l,r,rt);
    long long mid=l+r>>1;
    if(L<=mid)  
        updatemax(l,mid,rt<<1,L,R,c);
    if(R>mid)
        updatemax(mid+1,r,rt<<1|1,L,R,c);
    pushup(rt);
}
void updatemin(long long l,long long r,int rt,int L,int R,long long c){
    if(tree[rt].maxx<=c)
        return ;
    if(L<=l&&r<=R&&tree[rt].smax<=c){
        lazy(r-l+1,rt,c-tree[rt].maxx,0,0);
        return ;
    }
    pushdown(l,r,rt);
    long long mid=l+r>>1;
    if(L<=mid)
        updatemin(l,mid,rt<<1,L,R,c);
    if(R>mid)
        updatemin(mid+1,r,rt<<1|1,L,R,c);
    pushup(rt);
}
node query(long long l,long long r,int rt,int L,int R){
    if(L<=l&&r<=R)
        return tree[rt];
    pushdown(l,r,rt);
    long long mid=l+r>>1;
    if(L>mid)
        return query(mid+1,r,rt<<1|1,L,R);
    else if(R<=mid)
        return query(l,mid,rt<<1,L,R);
    else   
        return query(l,mid,rt<<1,L,R)+query(mid+1,r,rt<<1|1,L,R);
}
int main(){
    long long n,m;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    build(1,n,1);
    scanf("%lld",&m);
    while(m--){
        int op,l,r;
        long long x;
        scanf("%d %d %d",&op,&l,&r);
        if(op==1){
            scanf("%lld",&x);
            updateadd(1,n,1,l,r,x);
        }
        else if(op==2){
            scanf("%lld",&x);
            updatemax(1,n,1,l,r,x);
        }
        else if(op==3){
            scanf("%lld",&x);
            updatemin(1,n,1,l,r,x);
        }
        else if(op==4){
            long long ans=query(1,n,1,l,r).sum;
            printf("%lld\n",ans);
        }
        else if(op==5){
            long long ans=query(1,n,1,l,r).maxx;
            printf("%lld\n",ans);
        }
        else{
            long long ans=query(1,n,1,l,r).minn;
            printf("%lld\n",ans);
        }
    }
    return 0;
}
2024/10/30 15:53
加载中...