QOJ6608 Descent of Dragons

修改只会使值从 \(x\) 变成 \(x+1\),这个对整体的值域变化是非常小的。

对于一个阈值 \(lim\),考虑 \(01\) 序列 \(A_{lim}\)\(A_{lim,i}=[a_i\ge lim]\)

对于一次修改,实际上就是让 \(A_{x+1,i}\leftarrow A_{x+1,i}\ \mathrm{or}\ A_{x,i}\)

这个 \(\mathrm{or}\) 不好维护,但是可以发现 \(A_{x+1,i}\) 总是 \(\le A_{x,i}\) 的,所以只要直接复制就做完了。而这个是可以线段树维护的。

#include <bits/stdc++.h>
using namespace std;

const int kN = 5e5 + 5, kS = kN * 60;
int n, q;

struct SGT {
  int tot = 0;
  int root[kN];
  int ls[kS], rs[kS], cnt[kS];
  int Copy(int x) {
    int p = ++tot;
    ls[p] = ls[x];
    rs[p] = rs[x];
    cnt[p] = cnt[x];
    return p;
  }
  void Up(int o) { cnt[o] = cnt[ls[o]] + cnt[rs[o]]; }
  void Build(int &o, int l, int r) {
    cnt[o = ++tot] = r - l + 1;
    if(l == r) return ;
    int mid = (l + r) >> 1;
    Build(ls[o], l, mid);
    Build(rs[o], mid + 1, r);
  }
  void Copy(int &o1, int o2, int l, int r, int x, int y) {
    if(!o2 || (l > y) || (r < x)) return ;
    if((l >= x) && (r <= y)) return void(o1 = o2);
    int mid = (l + r) >> 1;
    o1 = Copy(o1);
    Copy(ls[o1], ls[o2], l, mid, x, y);
    Copy(rs[o1], rs[o2], mid + 1, r, x, y);
    Up(o1);
  }
  bool Count(int o, int l, int r, int x, int y) {
    if(!o || (l > y) || (r < x)) return 0;
    if((l >= x) && (r <= y)) return cnt[o];
    int mid = (l + r) >> 1;
    return Count(ls[o], l, mid, x, y) || Count(rs[o], mid + 1, r, x, y);
  }
} sgt;

int main() {
  // freopen("1.in", "r", stdin);
  // freopen("1.out", "w", stdout);
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n >> q;
  sgt.Build(sgt.root[0], 1, n);
  while(q--) {
    int op, l, r, x;
    cin >> op >> l >> r;
    if(op == 1) {
      cin >> x;
      sgt.Copy(sgt.root[x + 1], sgt.root[x], 1, n, l, r);
    }else {
      int L = -1, R = kN;
      while(L + 1 < R) {
        int mid = (L + R) >> 1;
        sgt.Count(sgt.root[mid], 1, n, l, r) ? (L = mid) : (R = mid);
      }
      cout << L << "\n";
    }
  }
  return 0;
}
posted @ 2025-11-10 17:52  CJzdc  阅读(18)  评论(0)    收藏  举报