根据新套路,线段树 + 值域分块。
因为卡空间所以底层分块(线段树叶子节点代表一块,pushup/down 的时候暴力)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 500005, M = 65536, B = 14, K = 16, INF = 0x7f7f7f7f;
template<typename T>
void rd(T &x){
int ch = getchar(); x = 0;
for(;ch < '0' || ch > '9';ch = getchar());
for(;ch >= '0' && ch <= '9';ch = getchar()) x = x * 10 + ch - '0';
}
template<typename T>
bool chmax(T &a, const T &b){if(a < b) return a = b, 1; return 0;}
template<typename T>
bool chmin(T &a, const T &b){if(a > b) return a = b, 1; return 0;}
int n, m, a[N], mx[8][M], mn[8][M], ct[8][M], tag[8][M], pw[9];
LL sum[8][M];
int get(int x){return upper_bound(pw, pw+9, x) - pw - 1;}
void bdown(int _, int L, int R, int x){
if(!tag[_][x]) return;
for(int i = L;i <= R;++ i)
if(a[i] >= pw[_] && a[i] < pw[_+1]) a[i] -= tag[_][x];
tag[_][x] = 0;
}
void bup(int _, int L, int R, int x){
sum[_][x] = ct[_][x] = mx[_][x] = 0; mn[_][x] = INF;
for(int i = L;i <= R;++ i) if(a[i] >= pw[_] && a[i] < pw[_+1]){
sum[_][x] += a[i]; ++ct[_][x];
chmax(mx[_][x], a[i]);
chmin(mn[_][x], a[i]);
}
}
void pup(int _, int x){
ct[_][x] = ct[_][x<<1] + ct[_][x<<1|1];
sum[_][x] = sum[_][x<<1] + sum[_][x<<1|1];
mx[_][x] = max(mx[_][x<<1], mx[_][x<<1|1]);
mn[_][x] = min(mn[_][x<<1], mn[_][x<<1|1]);
}
void ptag(int _, int x, int v){
if(!ct[_][x]) return;
tag[_][x] += v; mx[_][x] -= v; mn[_][x] -= v;
sum[_][x] -= (LL)ct[_][x] * v;
}
void pdown(int _, int x){
if(!tag[_][x]) return;
ptag(_, x<<1, tag[_][x]);
ptag(_, x<<1|1, tag[_][x]);
tag[_][x] = 0;
}
void ins(int _, int p, int v, int x = 1, int L = 1, int R = n){
if(R - L < K){
bdown(_, L, R, x); a[p] = v;
bup(_, L, R, x); return;
}
int md = L+R>>1; pdown(_, x);
if(p <= md) ins(_, p, v, x<<1, L, md);
else ins(_, p, v, x<<1|1, md+1, R);
pup(_, x);
}
LL Sum; int Mn, Mx;
void bqry(int _, int L, int R){
for(int i = L;i <= R;++ i) if(a[i] >= pw[_] && a[i] < pw[_+1]){
chmin(Mn, a[i]); chmax(Mx, a[i]); Sum += a[i];
}
}
void qry(int _, int l, int r, int x = 1, int L = 1, int R = n){
if(l <= L && R <= r){
Sum += sum[_][x]; chmin(Mn, mn[_][x]);
chmax(Mx, mx[_][x]); return;
}
if(R - L < K){
bdown(_, L, R, x);
bqry(_, max(L,l), min(R,r));
return;
}
int md = L+R>>1; pdown(_, x);
if(l <= md) qry(_, l, r, x<<1, L, md);
if(md < r) qry(_, l, r, x<<1|1, md+1, R);
}
void bupd(int _, int L, int R, int v){
for(int i = L;i <= R;++ i)
if(a[i] >= pw[_] && a[i] < pw[_+1] && a[i] > v && (a[i] -= v) < pw[_])
ins(get(a[i]), i, a[i]);
}
void upd(int _, int l, int r, int v, int x = 1, int L = 1, int R = n){
if(mx[_][x] <= v) return; // It's <=, not <
if(R - L < K){
bdown(_, L, R, x);
bupd(_, max(L,l), min(R,r), v);
bup(_, L, R, x); return;
}
if(l <= L && R <= r && mn[_][x] >= v+pw[_]){
ptag(_, x, v); return;
}
int md = L+R>>1; pdown(_, x);
if(l <= md) upd(_, l, r, v, x<<1, L, md);
if(md < r) upd(_, l, r, v, x<<1|1, md+1, R);
pup(_, x);
}
int main(){
rd(n); rd(m);
memset(mn, 0x7f, sizeof mn); pw[0] = 1;
for(int i = 0;i < 8;++ i) pw[i+1] = B*pw[i];
for(int i = 1;i <= n;++ i){
rd(a[i]); ins(get(a[i]), i, a[i]);
}
while(m --){
int op, l, r, x;
rd(op); rd(l); rd(r);
l ^= Sum; r ^= Sum;
assert(l >= 1 && r <= n && l <= r);
if(op == 1){
rd(x); x ^= Sum;
for(int i = 0;i < 8;++ i) upd(i, l, r, x);
} else {
Sum = Mx = 0; Mn = INF;
for(int i = 0;i < 8;++ i) qry(i, l, r);
printf("%lld %d %d
", Sum, Mn, Mx); Sum &= 1048575;
}
}
}