2024最后一天了,家人们救救我吧
查看原帖
2024最后一天了,家人们救救我吧
539345
OrinLoong楼主2024/12/31 10:56
#include <bits/stdc++.h>
using namespace std;
typedef long long lolo;
const int MaxN=5e5+5,Mod=(1<<20),Inf=0x3f3f3f3f;
const int snc=5e4+5,bbs=32,dbb=16,dbn=8;
void maxxer(int &x,int &y){x=max(x,y);}
void minner(int &x,int &y){x=min(x,y);}
int frdint(){
    int n=0,k=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')k=-1;ch=getchar();}
    while(isdigit(ch)){n=(n<<3)+(n<<1)+ch-'0',ch=getchar();}
    return n*k;
}
void fwrint(int x){
    if(x>9)fwrint(x/10);
    putchar(x%10+'0');
}
void fwrlolo(lolo x){
    if(x>9)fwrlolo(x/10);
    putchar(x%10+'0');
}
int N,M,A[MaxN],Opt,X,Y;lolo Z;
int lb[dbn],rb[dbn],sans,maax,miin;
void traner(int i);
struct SegmentTree{
    int mx[snc],mn[snc],cnt[snc];
    int id;lolo tag[snc],sum[snc];
    int ls(int p){return p<<1;}
    int rs(int p){return (p<<1)|1;}
    void init(int i){
        lb[i]=(i==0?1:rb[i-1]+1);
        rb[i]=lb[i]*dbb-1;id=i;
        memset(tag,0,sizeof(tag));
        memset(mx,0,sizeof(mx));
        memset(mn,0x3f,sizeof(mn));
        memset(cnt,0,sizeof(cnt));
        memset(sum,0,sizeof(sum));
        //初始化
    }
    void pushup(int p){
        cnt[p]=cnt[ls(p)]+cnt[rs(p)];
        sum[p]=sum[ls(p)]+sum[rs(p)];
        mx[p]=max(mx[ls(p)],mx[rs(p)]);
        mn[p]=min(mn[ls(p)],mn[rs(p)]);
    }//显然。
    void maketag(int p,lolo &val){
        tag[p]+=val,sum[p]-=val*cnt[p];
        mx[p]-=val,mn[p]-=val;
    }//显然。
    void pushdown(int p){
        if(!tag[p])return;
        if(cnt[ls(p)])maketag(ls(p),tag[p]);
        if(cnt[rs(p)])maketag(rs(p),tag[p]);
        tag[p]=0;
    }//显然。
    void bushup(int p,int cl,int cr){
        cnt[p]=0,sum[p]=0,mx[p]=0,mn[p]=Inf;
        for(int i = cl;i <= cr;i++){
            if(A[i]>=lb[id]&&A[i]<=rb[id]){
                cnt[p]++,sum[p]+=A[i];
                maxxer(mx[p],A[i]),minner(mn[p],A[i]);
            }
        }
    }
    //块上传
    void bushdown(int cl,int cr,lolo &val){
        if(!val)return;
        for(int i = cl;i <= cr;i++){
            if(A[i]>=lb[id]&&A[i]<=rb[id])A[i]-=val;
        }
        val=0;
    }
    //块下传
    void insert(int p,int cl,int cr,int dd,int val){
        if(cr-cl+1<=bbs){
            bushdown(cl,cr,tag[p]);A[dd]=val;
            bushup(p,cl,cr);return;
        }
        int mid=(cl+cr)>>1;pushdown(p);
        if(dd<=mid)insert(ls(p),cl,mid,dd,val);
        if(dd>mid)insert(rs(p),mid+1,cr,dd,val);
        pushup(p);
    }
    //往线段树里加入新值
    void ubdate(int cl,int cr,int x){
        for(int i = cl;i <= cr;i++){
            if(A[i]>=lb[id]&&A[i]<=rb[id]&&A[i]>x){
                A[i]-=x;if(A[i]<lb[i])traner(i);
            }
        }
    }
    //块内更新
    void buery(int cl,int cr,int dl,int dr){
        for(int i = max(cl,dl);i <= min(cr,dr);i++){
            if(A[i]>=lb[id]&&A[i]<=rb[id]){
                sans+=A[i],maxxer(maax,A[i]),minner(miin,A[i]);
            }
        }
    }
    //块上询问
    void update(int p,int cl,int cr,int dl,int dr,lolo val){
        if(mx[p]<=val)return;
        if(cr-cl+1<=bbs){
            bushdown(cl,cr,tag[p]);
            maxxer(dl,cl),minner(dr,cr);
            ubdate(dl,dr,val);bushup(p,cl,cr);
            return;
        }
        if(dl<=cl&&cr<=dr&&mn[p]-lb[id]>=val){
            maketag(p,val);return;
        }
        int mid=(cl+cr)>>1;pushdown(p);
        if(cl<=mid)update(ls(p),cl,mid,dl,dr,val);
        if(cr>mid)update(rs(p),mid+1,cr,dl,dr,val);
        pushup(p);
    }
    //更新
    void query(int p,int cl,int cr,int dl,int dr){
        if(dl<=cl&&cr<=dr){
            maxxer(maax,mx[p]),minner(miin,mn[p]);
            sans+=sum[p];return;
        }
        if(cr-cl+1<=bbs){
            bushdown(cl,cr,tag[p]);
            buery(cl,cr,dl,cr);
            bushup(p,cl,cr);return;
        }
        int mid=(cl+cr)>>1;pushdown(p);
        if(dl<=mid)query(ls(p),cl,mid,dl,dr);
        if(dr>mid)query(rs(p),mid+1,cr,dl,dr);
        pushup(p);
    }
    //询问
}SegTr[dbn];//一棵线段树对应一块倍增块
int getblk(int x){
    int cur=0;
    while(x>rb[cur])cur++;
    return cur;
}
//找值对应的块
void traner(int i){SegTr[getblk(A[i])].insert(1,1,N,i,A[i]);}
//由于我把每个倍增块的线段树分开了,所以我需要一个函数去把这个值跌到下一个块。
void psp(){putchar(' ');}//打印一个空格
int main(){
    // freopen("smp1.in","r",stdin);
    // freopen("myans1.out","w",stdout);
    N=frdint(),M=frdint();
    for(int i = 0;i < dbn;i++)SegTr[i].init(i);
    for(int i = 1;i <= N;i++){
        A[i]=frdint();SegTr[getblk(A[i])].insert(1,1,N,i,A[i]);
    }
    while(M--){
        Opt=frdint(),X=frdint()^sans,Y=frdint()^sans;
        if(Opt==1){
            Z=frdint()^sans;for(int i = 0;i < dbn;i++){
                if(rb[i]>=Z)SegTr[i].update(1,1,N,X,Y,Z);
            }
        }
        if(Opt==2){
            sans=0,maax=0,miin=Inf;
            for(int i = 0;i < dbn;i++)SegTr[i].query(1,1,N,X,Y);
            // putchar('x');
            fwrlolo(sans),psp(),fwrint(miin),psp(),fwrint(maax);
            puts("");sans%=Mod;
        }
    }
    return 0;
}

较多借鉴了这位奆佬的题解,马蜂良好而精悍,去掉注释只有153行。若调试出来,玄2关注。

2024/12/31 10:56
加载中...