[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;
    }
  }

}
posted @ 2025-05-13 15:21  CuFeO4  阅读(33)  评论(0)    收藏  举报