[Ynoi2007] rgxsxrs题解
打了 \(3\times 2 = 6\) 节课,重构了 \(3\) 次,然后又卡了一节课常才过了。
倍增值域分块板子,然后每块建一颗 \(1\sim n\) 的线段树。显然每个数最多只会跳 \(log V\) 次块,所以时间复杂度为 \(n\log n\log V\)。空间复杂度 \(n\log V\)。
发现空间过不去,考虑经典卡空间套路,线段树不要叶子节点了,直接把几个叶子合并到一起分块处理。
平衡一下,时间复杂度并不变,空间复杂度 \(O(n)\)。
关于卡常:非必要的话底层块的懒标记不更新。
由于一些奇奇怪怪的问题,倍增底数取 \(32\)。本题并不卡常,倍增底数取 \(32\) 就行了。
实现使用的奇奇怪怪的线段树。
code
#include<bits/stdc++.h>
using namespace std;
using ll = long long;using ull = unsigned long long;
using db = double;using ldb = long double;
auto ckx = [](auto &x,const auto &y){((x < y) && (x = y));};
auto ckm = [](auto &x,const auto &y){((x > y) && (x = y));};
#define IL inline
const int N = 5e5 + 10;
const int B = 30;
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#define fpu(x) fputc_unlocked((x), _of)
#ifdef LOCAL
int _if = open("in.in", O_RDONLY);
FILE* _of = fopen("out.out", "w");
#else
int _if = fileno(stdin);
FILE* _of = stdout;
#endif
const char *_I = (char*) mmap(nullptr, lseek(_if, 0, SEEK_END), PROT_READ, MAP_PRIVATE, _if, 0);
template <typename T = int>
inline T _R() {
T x = 0;
for (; *_I < 48; ++_I);
for (; *_I > 47; ++_I) x = x * 10 + (*_I & 15);
return x;
}
template <typename T>
IL void _W(T x) {
if (x > 9) _W(x/10);
fpu(48 + x % 10);
}
int test,testid;
int n,m,a[N],bel[N],rb[N],L[N/B+3],R[N/B+3];
int pw[20];
struct node{
int ct,Max,Min;ll sum;
node(){ct = Max = sum = 0;Min = 1e9;}
node(int _ct,int _Max,int _Min,ll _sum){
ct = _ct,Max = _Max,Min = _Min,sum = _sum;
}
IL node operator + (const node &x){
return node(ct+x.ct,max(Max,x.Max),min(Min,x.Min),sum+x.sum);
}
IL node operator + (const int &x){
return node(ct,Max+x,Min+x,sum+1ll*x*ct);
}
};
vector<int> ch;
struct Block{
int id,ct,Max,Min,tag,l,r;ll sum;
Block(){ct = Max = sum = 0,Min = 1e9;}
IL void build(int _l,int _r,int _id){
l = _l,r = _r,id = _id;
ct = Max = sum = 0;Min = 1e9;
for(int i = l;i <= r; ++i){
if(rb[i] == id){
ct++,sum += a[i],ckx(Max,a[i]),ckm(Min,a[i]);
}
}
}
IL node Get(){return node(ct,Max,Min,sum);}
IL void mklz(int val){tag += val;sum += 1ll*val*ct;Max += val,Min += val;}
IL node Q(int ql,int qr){
int ct = 0,Max = 0,Min = 1e9;ll sum = 0;
for(int i = ql;i <= qr; ++i){
if(rb[i] == id) ct++,ckx(Max,a[i]),ckm(Min,a[i]),sum += a[i];
}
Max += tag;Min += tag;sum += 1ll*ct*tag;
return node(ct,Max,Min,sum);
}
IL void C(int ql,int qr,int val){
sum = 0,Max = 0,ct = 0,Min = 1e9;
for(int i = ql;i <= qr; ++i)
if(rb[i] == id && a[i] + tag > -val) a[i] += val;
for(int i = l;i <= r; ++i){
if(rb[i] == id) ct++,sum += a[i],ckx(Max,a[i]),ckm(Min,a[i]);
}
Max += tag,Min += tag,sum += 1ll*tag*ct;
}
IL void needchange(int v){
if(tag){
for(int i = l;i <= r; ++i) if(rb[i] == id) a[i] += tag;
tag = 0;
}
ct = sum = Max = 0;Min = 1e9;
for(int i = l;i <= r; ++i){
if(rb[i] == id){
if(a[i] < v) rb[i] = 0,ch.emplace_back(i);
else ct++,ckx(Max,a[i]),ckm(Min,a[i]),sum += a[i];
}
}
}
IL void pushdown(){
if(!tag) return;
for(int i = l;i <= r; ++i) if(rb[i] == id) a[i] += tag;
tag = 0;
}
}blk[N];int tot;
struct Segment_Tree{
private:
void U(int k,int mid){t[k].val = t[mid<<1].val + t[mid<<1|1].val;}
void build(int k,int l,int r){
if(l == r){
int id = l + more;
blk[id].build(L[l],R[l],id);
t[k].val = blk[id].Get();
return;
}
int mid = (l + r) >> 1;
build(mid<<1,l,mid),build(mid<<1|1,mid+1,r);
U(k,mid);
}
void maketag(int k,int val){t[k].val = t[k].val + val;t[k].tag += val;}
void pushdown(int k,int mid,int l,int r){
if(!t[k].tag) return;
if(l == mid){
int id = l + more;
blk[id].mklz(t[k].tag);
if(blk[id].Min < v) blk[id].needchange(v);
t[mid<<1].val = blk[id].Get();
}
else maketag(mid<<1,t[k].tag);
if(mid+1 == r){
int id = r + more;
blk[id].mklz(t[k].tag);
if(blk[id].Min < v) blk[id].needchange(v);
t[mid<<1|1].val = blk[id].Get();
}
else maketag(mid<<1|1,t[k].tag);
t[k].tag = 0;
}
void C(int ql,int qr,int x,int k,int l,int r){
if(t[k].val.Max <= x - v) return;
if(l == r){
int id = l + more;
blk[id].C(max(ql,blk[id].l),min(qr,blk[id].r),v-x);
if(blk[id].Min < v) blk[id].needchange(v);
t[k].val = blk[id].Get();
return;
}
if(ql <= L[l] && R[r] <= qr && t[k].val.Min >= x){
return maketag(k,v-x);
}
int mid = (l + r) >> 1;
pushdown(k,mid,l,r);
if(ql <= R[mid]) C(ql,qr,x,mid<<1,l,mid);
if(qr > R[mid]) C(ql,qr,x,mid<<1|1,mid+1,r);
U(k,mid);
}
node Q(int ql,int qr,int k,int l,int r){
if(!t[k].val.ct) return node();
if(l == r){
int id = l + more;
return blk[id].Q(max(ql,blk[id].l),min(qr,blk[id].r));
}
if(ql <= L[l] && R[r] <= qr) return t[k].val;
int mid = (l + r) >> 1;node res;pushdown(k,mid,l,r);
if(ql <= R[mid]) res = res + Q(ql,qr,mid<<1,l,mid);
if(qr > R[mid]) res = res + Q(ql,qr,mid<<1|1,mid+1,r);
return res;
}
void I(int p,int k,int l,int r){
if(l == r){
int id = l + more;
blk[id].pushdown();
rb[p] = id;
ckx(blk[id].Max,a[p]);
ckm(blk[id].Min,a[p]);
blk[id].sum += a[p];
blk[id].ct++;
t[k].val = blk[id].Get();
return;
}
int mid = (l + r) >> 1;
pushdown(k,mid,l,r);
p <= R[mid]?I(p,mid<<1,l,mid):I(p,mid<<1|1,mid+1,r);
U(k,mid);
}
public:
int Right,v,more;
struct seg{node val;int tag;}t[(N/B+1)<<1];
void build(){build(1,1,Right);}
void C(int ql,int qr,int x){C(ql,qr,x,1,1,Right);}
node Q(int ql,int qr){return Q(ql,qr,1,1,Right);}
void I(int p){I(p,1,1,Right);}
}sgt[6];
IL int _lg(const int &x){return log(x)/log(32);}
IL void change(){
for(auto p:ch) sgt[_lg(a[p])].I(p);
ch.clear();
}
signed main(){
n = _R(),m = _R();for(int i = 1;i <= n; ++i) a[i] = _R();
for(int i = 1;i <= n; ++i){
bel[i] = i/B+1;
if(bel[i] != bel[i-1]) L[bel[i]] = i,R[bel[i-1]] = i - 1;
}
R[bel[n]] = n;
pw[0] = 1;
for(int i = 1;i < 7; ++i) pw[i] = pw[i-1]*32;
for(int i = 0;i < 6; ++i){
int bg = tot + 1,ed = tot;
for(int j = 1;j <= n; ++j){
if(bel[j] != bel[j-1]){
ed++;
if(j != 1) blk[ed-1].r = j - 1;
blk[ed].l = j,blk[ed].id = ed;
}
if(pw[i] <= a[j] && a[j] < pw[i+1]) rb[j] = ed;
}
tot = ed;blk[ed].r = n;
sgt[i].v = pw[i];
sgt[i].more = bg - 1,sgt[i].Right = ed - bg + 1;
sgt[i].build();
}
int lastans = 0;const int Mod = (1<<20)-1;
for(test = 1;test <= m; ++test){
int op,l,r,x = 0;
op = _R(),l = _R(),r = _R();
if(op == 1){
x = _R();
l ^= lastans,r ^= lastans,x ^= lastans;
for(int i = 0;i < 6; ++i){
sgt[i].C(l,r,x + sgt[i].v);
}
change();
}
else{
l ^= lastans,r ^= lastans;
node res;
for(int i = 0;i < 6; ++i){
res = res + sgt[i].Q(l,r);
}
_W(res.sum);fpu(' ');_W(res.Min);fpu(' ');_W(res.Max);fpu('\n');
lastans = res.sum&Mod;
}
}
}
__________________________________________________________________________________________
本文来自博客园,作者:CuFeO4,转载请注明原文链接:https://www.cnblogs.com/hzoi-Cu/p/18874327