zoukankan      html  css  js  c++  java
  • 「BZOJ3065」带插入区间K小值 [分块]

    考虑分块,每个块都是用 链表 维护的,并保证 (size) 和分块相当。

    我们考虑一下怎么去查询,很显然,可以对值域分块,单点修改,记录前缀和,完全ojbk了,对每个块维护一个 (pre , prb) 数组

    (pre_{i,j}) 数组表示 (1~i) 这些块中,出现了多少个 (j)
    (prb_{i,j}) 数组表示 (1~i) 这些块中,在值域块 (j) 的有多少个
    零散部分查一查就好了,修改也是稳定 (sqrt n) 的,插入也是。

    // powered by c++11
    // by Isaunoya
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("unroll-loops")
    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    #include <bits/stdc++.h>
    #define rep(i, x, y) for (register int i = (x); i <= (y); ++i)
    #define Rep(i, x, y) for (register int i = (x); i >= (y); --i)
    using namespace std;
    using db = double;
    using ll = long long;
    using uint = unsigned int;
    using pii = pair<int, int>;
    #define ve vector
    #define Tp template
    #define all(v) v.begin(), v.end()
    #define sz(v) ((int)v.size())
    #define pb emplace_back
    #define fir first
    #define sec second
    // the cmin && cmax
    Tp<class T> void cmax(T& x, const T& y) {
      if (x < y) x = y;
    }
    Tp<class T> void cmin(T& x, const T& y) {
      if (x > y) x = y;
    }
    // sort , unique , reverse
    Tp<class T> void sort(ve<T>& v) { sort(all(v)); }
    Tp<class T> void unique(ve<T>& v) {
      sort(all(v));
      v.erase(unique(all(v)), v.end());
    }
    Tp<class T> void reverse(ve<T>& v) { reverse(all(v)); }
    const int SZ = 0x191981;
    struct FILEIN {
      char qwq[SZ], *S = qwq, *T = qwq, ch;
      char GETC() { return (S == T) && (T = (S = qwq) + fread(qwq, 1, SZ, stdin), S == T) ? EOF : *S++; }
      FILEIN& operator>>(char& c) {
        while (isspace(c = GETC()))
          ;
        return *this;
      }
      FILEIN& operator>>(string& s) {
        while (isspace(ch = GETC()))
          ;
        s = ch;
        while (!isspace(ch = GETC())) s += ch;
        return *this;
      }
      Tp<class T> void read(T& x) {
        bool sign = 1;
        while ((ch = GETC()) < 0x30)
          if (ch == 0x2d) sign = 0;
        x = (ch ^ 0x30);
        while ((ch = GETC()) > 0x2f) x = x * 0xa + (ch ^ 0x30);
        x = sign ? x : -x;
      }
      FILEIN& operator>>(int& x) { return read(x), *this; }
      FILEIN& operator>>(unsigned& x) { return read(x), *this; }
    } in;
    struct FILEOUT {
      const static int LIMIT = 0x114514;
      char quq[SZ], ST[0x114];
      signed sz, O;
      ~FILEOUT() { flush(); }
      void flush() {
        fwrite(quq, 1, O, stdout);
        fflush(stdout);
        O = 0;
      }
      FILEOUT& operator<<(char c) { return quq[O++] = c, *this; }
      FILEOUT& operator<<(string str) {
        if (O > LIMIT) flush();
        for (char c : str) quq[O++] = c;
        return *this;
      }
      Tp<class T> void write(T x) {
        if (O > LIMIT) flush();
        if (x < 0) {
          quq[O++] = 0x2d;
          x = -x;
        }
        do {
          ST[++sz] = x % 0xa ^ 0x30;
          x /= 0xa;
        } while (x);
        while (sz) quq[O++] = ST[sz--];
        return;
      }
      FILEOUT& operator<<(int x) { return write(x), *this; }
      FILEOUT& operator<<(unsigned x) { return write(x), *this; }
    } out;
    int n, m;
    const int maxn = 7e4 + 47;
    const int blc = 235;
    const int S = 300;
    list<int> s[S];
    #define bl(x) ((x - 1) / S + 1)
    int pre[maxn][S], prb[S][S], L[S], R[S], cnt[maxn], t[S], st[S << 1], top = 0, ans = 0;
    inline int modify(list<int>& l, int x, int v) {
      auto it = l.begin();
      while (x--) ++it;
      int res = *(it);
      return *(it) = v, res;
    }
    inline void get(list<int>& l, int x, int y) {
      auto it = l.begin();
      while (x--) ++it;
      while (y--) {
        ++cnt[st[++top] = *(it)], ++t[bl(*(it))], ++it;
      }
    }
    void qry(int l, int r, int k) {
      top = 0;
      const int bL = bl(l), bR = bl(r);
      if (bL == bR) {
        get(s[bL], l - L[bL], r - l + 1);
        for (int i = 1;; i++) {
          if (k > t[i]) {
            k -= t[i];
          } else {
            for (int j = L[i];; ++j)
              if (k > cnt[j]) {
                k -= cnt[j];
              } else {
                ans = j;
                break;
              }
            break;
          }
        }
      } else {
        get(s[bL], l - L[bL], R[bL] - l + 1), get(s[bR], 0, r - L[bR] + 1);
        for (int i = 1;; i++) {
          if (k > t[i] + prb[i][bR - 1] - prb[i][bL]) {
            k -= (t[i] + prb[i][bR - 1] - prb[i][bL]);
          } else {
            for (int j = L[i];; ++j)
              if (k > cnt[j] + pre[j][bR - 1] - pre[j][bL]) {
                k -= (cnt[j] + pre[j][bR - 1] - pre[j][bL]);
              } else {
                ans = j;
                break;
              }
            break;
          }
        }
      }
      ans--;
      for (int i = 0; i <= top; i++) {
        t[bl(st[i])] = 0, cnt[st[i]] = 0;
      }
    }
    inline void change(int x, int v) {
      const int bel = bl(x);
      int las = modify(s[bel], x - L[bel], v);
      for (int i = bel; i <= blc; i++) {
        --pre[las][i], --prb[bl(las)][i], ++pre[v][i], ++prb[bl(v)][i];
      }
    }
    inline void ins(int x, int v) {
      const int bel = bl(x);
      auto it = s[bel].begin();
      for (int i = x - L[bel]; i--;) ++it;
      s[bel].insert(it, v);
      for (int i = bel; i <= blc; i++) {
        ++pre[v][i], ++prb[bl(v)][i];
      }
      for (int i = bel + 1; i <= blc; i++) {
        if (s[i - 1].size() <= S) {
          break;
        } else {
          int las = s[i - 1].back();
          --pre[las][i - 1], --prb[bl(las)][i - 1];
          s[i - 1].pop_back(), s[i].push_front(las);
        }
      }
    }
    signed main() {
    #ifdef _WIN64
      freopen("testdata.in", "r", stdin);
    #else
      ios_base ::sync_with_stdio(false);
      cin.tie(nullptr), cout.tie(nullptr);
    #endif
      // code begin.
      in >> n;
      rep(i, 1, blc) { L[i] = R[i - 1] + 1, R[i] = L[i] + S - 1; }
      rep(i, 1, n) {
        int x;
        const int bel = bl(i);
        in >> x, ++x, s[bel].pb(x);
        rep(j, bel, blc) { ++pre[x][j], ++prb[bl(x)][j]; }
      }
      in >> m;
      while (m--) {
        char c;
        in >> c;
        if (c == 'Q') {
          int l, r, k;
          in >> l >> r >> k, qry(l ^ ans, r ^ ans, k ^ ans), out << ans << '
    ';
        }
        if (c == 'M') {
          int x, v;
          in >> x >> v, x ^= ans, v ^= ans, ++v, change(x, v);
        }
        if (c == 'I') {
          int x, v;
          in >> x >> v, x ^= ans, v ^= ans, ++v, ins(x, v);
        }
      }
      return 0;
      // code end.
    }
    
  • 相关阅读:
    Cannot load php5apache2_4.dll into server
    goroutine,channel
    为什么 Go 标准库中有些函数只有签名,没有函数体?
    PHP编码风格规范
    etcd压测造成数据目录过大恢复
    高可用kubernetes集群查看kube-scheduler和kube-controller-manager哪个是leader节点
    kubeadm join添加节点,新加节点夯在not ready(cni config uninitialized)
    一次.dockerignore设置错误导致的docker build排查
    通过开源插件实现sonarqube区分不同分支显示代码扫描结果
    python脚本,调用接口清理镜像多余tag
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12299733.html
Copyright © 2011-2022 走看看