zoukankan      html  css  js  c++  java
  • #4923. [Lydsy1706月赛]K小值查询 [平衡树,势能分析]

    草,不会做啊不会做啊不会做啊……

    题意:

    维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作:
    1 k,将序列a从小到大排序,输出a_k的值。
    2 k,将所有严格大于k的数a_i减去k。

    sol:

    平衡树,大家都会,减掉 (k) 后,相对位置发生改变的,只有 ([1,k])([k+1,2k])
    我们发现这个减法,如果减成功了,不会超过 (log) 次的。

    所以复杂度是 (n log^2 n),大概是和启发式合并一样>_<。

    具体点的做法大概就是,你根据值域分成三个部分,[1,k] && [k+1,2k] && [2k+1,inf]。
    然后我们只需要将 ([1,k])([k+1,2k]) 有序的合并就好了。
    怎么合并呢?你发现([k+1,2k])的权值的相对大小还是不变的,那么我们就直接递归把一个个点提取出来然后合并qwq。

      int Merge(int x, int y) {
        if (sz[x] < sz[y]) x ^= y ^= x ^= y;
        if (!y) return x;
        pushdown(x);
        pushdown(y);
        x = Merge(x, merge(ls[y], rs[y]));
        ls[y] = rs[y] = 0;
        sz[y] = 1;
        int qwq1, qwq2;
        split(x, qwq1, qwq2, val[y]);
        return x = merge(merge(qwq1, y), qwq2);
      }
    
    // powered by c++11
    // by Isaunoya
    #pragma GCC optimize(3)
    #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 ull = unsigned long long;
    
    using pii = pair<int, int>;
    
    #define fir first
    #define sec second
    
    template <class T>
    
    void cmax(T& x, const T& y) {
      if (x < y) x = y;
    }
    
    template <class T>
    
    void cmin(T& x, const T& y) {
      if (x > y) x = y;
    }
    
    #define all(v) v.begin(), v.end()
    #define sz(v) ((int)v.size())
    #define pb emplace_back
    
    template <class T>
    
    void sort(vector<T>& v) {
      sort(all(v));
    }
    
    template <class T>
    
    void reverse(vector<T>& v) {
      reverse(all(v));
    }
    
    template <class T>
    
    void unique(vector<T>& v) {
      sort(all(v)), v.erase(unique(all(v)), v.end());
    }
    
    void reverse(string& s) { reverse(s.begin(), s.end()); }
    
    const int io_size = 1 << 23 | 233;
    const int io_limit = 1 << 22;
    struct io_in {
      char ch;
    #ifndef __WIN64
      char getchar() {
        static char buf[io_size], *p1 = buf, *p2 = buf;
    
        return (p1 == p2) && (p2 = (p1 = buf) + fread(buf, 1, io_size, stdin), p1 == p2) ? EOF : *p1++;
      }
    #endif
      io_in& operator>>(char& c) {
        for (c = getchar(); isspace(c); c = getchar())
          ;
    
        return *this;
      }
      io_in& operator>>(string& s) {
        for (s.clear(); isspace(ch = getchar());)
          ;
    
        if (!~ch) return *this;
    
        for (s = ch; !isspace(ch = getchar()) && ~ch; s += ch)
          ;
    
        return *this;
      }
    
      io_in& operator>>(char* str) {
        char* cur = str;
        while (*cur) *cur++ = 0;
    
        for (cur = str; isspace(ch = getchar());)
          ;
        if (!~ch) return *this;
    
        for (*cur = ch; !isspace(ch = getchar()) && ~ch; *++cur = ch)
          ;
    
        return *++cur = 0, *this;
      }
    
      template <class T>
    
      void read(T& x) {
        bool f = 0;
        while ((ch = getchar()) < 48 && ~ch) f ^= (ch == 45);
    
        x = ~ch ? (ch ^ 48) : 0;
        while ((ch = getchar()) > 47) x = x * 10 + (ch ^ 48);
        x = f ? -x : x;
      }
    
      io_in& operator>>(int& x) { return read(x), *this; }
    
      io_in& operator>>(ll& x) { return read(x), *this; }
    
      io_in& operator>>(uint& x) { return read(x), *this; }
    
      io_in& operator>>(ull& x) { return read(x), *this; }
    
      io_in& operator>>(db& x) {
        read(x);
        bool f = x < 0;
        x = f ? -x : x;
        if (ch ^ '.') return *this;
    
        double d = 0.1;
        while ((ch = getchar()) > 47) x += d * (ch ^ 48), d *= .1;
        return x = f ? -x : x, *this;
      }
    } in;
    
    struct io_out {
      char buf[io_size], *s = buf;
      int pw[233], st[233];
    
      io_out() {
        set(7);
        rep(i, pw[0] = 1, 9) pw[i] = pw[i - 1] * 10;
      }
    
      ~io_out() { flush(); }
    
      void io_chk() {
        if (s - buf > io_limit) flush();
      }
    
      void flush() { fwrite(buf, 1, s - buf, stdout), fflush(stdout), s = buf; }
    
      io_out& operator<<(char c) { return *s++ = c, *this; }
    
      io_out& operator<<(string str) {
        for (char c : str) *s++ = c;
        return io_chk(), *this;
      }
    
      io_out& operator<<(char* str) {
        char* cur = str;
        while (*cur) *s++ = *cur++;
        return io_chk(), *this;
      }
    
      template <class T>
    
      void write(T x) {
        if (x < 0) *s++ = '-', x = -x;
    
        do {
          st[++st[0]] = x % 10, x /= 10;
        } while (x);
    
        while (st[0]) *s++ = st[st[0]--] ^ 48;
      }
    
      io_out& operator<<(int x) { return write(x), io_chk(), *this; }
    
      io_out& operator<<(ll x) { return write(x), io_chk(), *this; }
    
      io_out& operator<<(uint x) { return write(x), io_chk(), *this; }
    
      io_out& operator<<(ull x) { return write(x), io_chk(), *this; }
    
      int len, lft, rig;
    
      void set(int _length) { len = _length; }
    
      io_out& operator<<(db x) {
        bool f = x < 0;
        x = f ? -x : x, lft = x, rig = 1. * (x - lft) * pw[len];
        return write(f ? -lft : lft), *s++ = '.', write(rig), io_chk(), *this;
      }
    } out;
    #define int long long
    
    template <int sz, int mod>
    
    struct math_t {
      math_t() {
        fac.resize(sz + 1), ifac.resize(sz + 1);
        rep(i, fac[0] = 1, sz) fac[i] = fac[i - 1] * i % mod;
    
        ifac[sz] = inv(fac[sz]);
        Rep(i, sz - 1, 0) ifac[i] = ifac[i + 1] * (i + 1) % mod;
      }
    
      vector<int> fac, ifac;
    
      int qpow(int x, int y) {
        int ans = 1;
        for (; y; y >>= 1, x = x * x % mod)
          if (y & 1) ans = ans * x % mod;
        return ans;
      }
    
      int inv(int x) { return qpow(x, mod - 2); }
    
      int C(int n, int m) {
        if (n < 0 || m < 0 || n < m) return 0;
        return fac[n] * ifac[m] % mod * ifac[n - m] % mod;
      }
    };
    
    int gcd(int x, int y) { return !y ? x : gcd(y, x % y); }
    int lcm(int x, int y) { return x * y / gcd(x, y); }
    
    const int maxn = 1e5 + 51;
    
    template <int maxn>
    
    struct fhq {
      int rt, cnt;
      fhq() {
        rt = cnt = top = 0;
        srand(19260817);
      }
      int st[maxn], top;
      int val[maxn], ls[maxn], rs[maxn], sz[maxn], rnd[maxn];
      int tag[maxn];
    
      void pushtag(int x, int v) {
        tag[x] += v;
        val[x] -= v;
      }
    
      void pushdown(int x) {
        if (tag[x]) {
          if (ls[x]) {
            pushtag(ls[x], tag[x]);
          }
          if (rs[x]) {
            pushtag(rs[x], tag[x]);
          }
          tag[x] = 0;
        }
      }
    
      void pushup(int x) { sz[x] = sz[ls[x]] + sz[rs[x]] + 1; }
    
      int newnode(int v) {
        int now = top ? st[top--] : ++cnt;
        ls[now] = rs[now] = 0;
        val[now] = v;
        rnd[now] = rand();
        sz[now] = 1;
        return now;
      }
    
      int merge(int x, int y) {
        if (!x || !y) return x | y;
    
        pushdown(x);
        pushdown(y);
    
        if (rnd[x] < rnd[y]) {
          rs[x] = merge(rs[x], y);
          pushup(x);
          return x;
        } else {
          ls[y] = merge(x, ls[y]);
          pushup(y);
          return y;
        }
      }
    
      void split(int cur, int& x, int& y, int k) {
        if (!cur) {
          x = y = 0;
          return;
        }
        pushdown(cur);
        if (val[cur] <= k) {
          x = cur;
          split(rs[x], rs[x], y, k);
        } else {
          y = cur;
          split(ls[y], x, ls[y], k);
        }
        pushup(cur);
      }
    
      int qry(int x, int k) {
        pushdown(x);
        if (k <= sz[ls[x]]) {
          return qry(ls[x], k);
        }
        if (sz[ls[x]] + 1 == k) {
          return val[x];
        }
        return qry(rs[x], k - sz[ls[x]] - 1);
      }
    
      void ins(int v) {
        int x, y;
        split(rt, x, y, v);
        rt = merge(merge(x, newnode(v)), y);
      }
    
      int Merge(int x, int y) {
        if (sz[x] < sz[y]) x ^= y ^= x ^= y;
        if (!y) return x;
        pushdown(x);
        pushdown(y);
        x = Merge(x, merge(ls[y], rs[y]));
        ls[y] = rs[y] = 0;
        sz[y] = 1;
        int qwq1, qwq2;
        split(x, qwq1, qwq2, val[y]);
        return x = merge(merge(qwq1, y), qwq2);
      }
      void dec(int v) {
        int x, y, z;
        split(rt, x, y, v);
        split(y, y, z, v * 2);
        pushtag(y, v);
        pushtag(z, v);
        rt = merge(Merge(x, y), z);
      }
    };
    
    fhq<maxn> qwq;
    
    signed main() {
      // code begin.
      int _, __;
      in >> _ >> __;
      while (_--) {
        int ___;
        in >> ___;
        qwq.ins(___);
      }
      while (__--) {
        int op, k;
        in >> op >> k;
        if (op == 1) {
          out << qwq.qry(qwq.rt, k) << '
    ';
        } else {
          qwq.dec(k);
        }
      }
      return 0;
      // code end.
    }
    
  • 相关阅读:
    .Net网站的web.config配置说明
    listview垂直滚动条效果
    .net 委托事件
    利用API实现窗体淡入淡出特效
    易经中的64个大智慧
    FlashWindowEx实现窗口在任务栏闪烁/变化颜色
    实现XML与DataTable互转 .NET
    C# .NET弹出窗口
    SVN使用教程
    在IE中使用VS.net WinForm控件
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12595575.html
Copyright © 2011-2022 走看看