2020ICPC南京J

摆…… / 2023-05-05 / 原文

以前没写过势能线段树,然后错了114514个地方,我有罪。

#include<bits/stdc++.h>
using namespace std;
const int N=200013;
int a[N];
struct segtree{
#define mid ((l+r)>>1)
#define ls x<<1,l,mid
#define rs x<<1|1,mid+1,r
#define lc tr[x<<1]
#define rc tr[x<<1|1]
    struct info{
        int fi,fsz,se,c[32],xsm,tg;
    }tr[N<<2];
    void pu(int x){
        tr[x].xsm=lc.xsm^rc.xsm;
        for(int i=0;i<30;i++)tr[x].c[i]=lc.c[i]+rc.c[i];
        if(rc.fi>lc.fi)tr[x].fi=lc.fi,tr[x].fsz=lc.fsz,tr[x].se=min(lc.se,rc.fi);
        if(rc.fi<lc.fi)tr[x].fi=rc.fi,tr[x].fsz=rc.fsz,tr[x].se=min(rc.se,lc.fi);
        if(rc.fi==lc.fi)tr[x].fi=lc.fi,tr[x].fsz=lc.fsz+rc.fsz,tr[x].se=min(lc.se,rc.se);
    }
    void build(int x,int l,int r){
        tr[x].tg=-1;
        if(l==r){
            tr[x].xsm=tr[x].fi=a[l],tr[x].fsz=1;
            tr[x].se=(1<<30)-1;
            for(int i=0;i<30;i++)tr[x].c[i]=a[l]>>i&1;
            return;
        }
        build(ls),build(rs),pu(x);
    }
    void pd(int x){
        auto&t=tr[x].tg;
        if(t!=-1){
            if(lc.fi<t&&t<lc.se){
                for(int i=0;i<30;i++){
                    if(lc.fi>>i&1)lc.c[i]-=lc.fsz;
                    if(t>>i&1)lc.c[i]+=lc.fsz;
                }
                if(lc.fsz&1)lc.xsm^=lc.fi^t;
                lc.fi=lc.tg=t;
            }
            if(rc.fi<t&&t<rc.se){
                for(int i=0;i<30;i++){
                    if(rc.fi>>i&1)rc.c[i]-=rc.fsz;
                    if(t>>i&1)rc.c[i]+=rc.fsz;
                }
                if(rc.fsz&1)rc.xsm^=rc.fi^t;
                rc.fi=rc.tg=t;
            }
        }
        t=-1;
    }
    void add(int x,int l,int r,int L,int R,int val){
        if(L<=l&&R>=r){
            if(val<=tr[x].fi)return;
            else if(val<tr[x].se){
                for(int i=0;i<30;i++){
                    if(tr[x].fi>>i&1)tr[x].c[i]-=tr[x].fsz;
                    if(val>>i&1)tr[x].c[i]+=tr[x].fsz;
                }
                if(tr[x].fsz&1)tr[x].xsm^=tr[x].fi^val;
                tr[x].fi=tr[x].tg=val;
            }
            else pd(x),add(ls,L,R,val),add(rs,L,R,val),pu(x);
            return;
        }
        pd(x);
        if(L<=mid)add(ls,L,R,val);
        if(R>mid)add(rs,L,R,val);
        pu(x);
    }
    int qry(int x,int l,int r,int L,int R,int b){
        if(L<=l&&R>=r)return tr[x].c[b];
        int res=0;pd(x);
        if(L<=mid)res+=qry(ls,L,R,b);
        if(R>mid)res+=qry(rs,L,R,b);
        return res;
    }
    int qry(int x,int l,int r,int L,int R){
        if(L<=l&&R>=r)return tr[x].xsm;
        int res=0;pd(x);
        if(L<=mid)res^=qry(ls,L,R);
        if(R>mid)res^=qry(rs,L,R);
        return res;
    }
}T;

void work(){
    int n;cin>>n;
    int q;cin>>q;
    for(int i=1;i<=n;i++)cin>>a[i];
    T.build(1,1,n);
    for(int i=1,l,r,op,x;i<=q;i++){
        cin>>op>>l>>r>>x;
        if(op==1)T.add(1,1,n,l,r,x);
        else{
            int val=T.qry(1,1,n,l,r);
            if(val==x){
                cout<<0<<'\n';
                continue;
            }
            int xx=__lg(val^x);
            cout<<T.qry(1,1,n,l,r,xx)+(x>>xx&1)<<'\n';
        }
    }
}
int main(){
    cin.tie(0);
    ios::sync_with_stdio(0);
    cout.tie(0);
    int T=1; //cin>>T
    while(T--) work();
    return 0;
}