Loading

珂朵莉树

珂朵莉树

神奇的暴力数据结构

例题

\(n\) 个数,\(m\) 次操作 \((n,m≤105)\)

操作:

  • 区间加
  • 区间赋值
  • 区间第k小
  • 求区间幂次和

数据随机,时限 \(2s\)

关键操作:推平一段区间,使一整段区间内的东西变得一样。保证数据随机

#include <set>
#include <vector>
#define p 1000000007
#define IT set<node>::iterator

/* 初始化 */
struct node
{
    ll l, r;
    mutable ll w; //可变的
    node(ll L, ll R = -1, ll W = 0)
    {
        l = L;
        r = R;
        w = W;
    }
    bool operator<(const node &o) const
    {
        return l < o.l;
    }
};


ll n, m, seed, vmax, a[100005];
set<node> s;

ll rnd() /* 对于本题的数据生成器 */
{
    ll ans = seed;
    seed = (seed * 7 + 13) % p;
    return ans;
}

ll ksm(){}

IT split(ll pos) /* 分裂 */
{
    IT it = s.lower_bound(node(pos));
    if (it != s.end() && it->l == pos)
        return it;
    --it;
    ll L = it->l, R = it->r;
    ll W = it->w;
    s.erase(it);
    s.insert(node(L, pos - 1, W));
    return s.insert(node(pos, R, W)).first;
}

void assign(ll l, ll r, ll w = 0) /* 推平 */
{
    IT itl = split(l), itr = split(r + 1);
    s.erase(itl, itr);
    s.insert(node(l, r, w));
}

void add(ll l, ll r, ll w = 1) /* 暴力区间加 */
{
    IT itl = split(l), itr = split(r + 1);
    for (; itl != itr; ++itl)
        itl->w += w;
}

ll rnk(ll l, ll r, ll k) /* 暴力区间第 k 小 */
{
    vector<pair<ll, int>> vp;
    IT itl = split(l), itr = split(r + 1);
    vp.clear();
    for (; itl != itr; ++itl)
        vp.push_back(pair<ll, int>(itl->w, itl->r - itl->l + 1));
    std::sort(vp.begin(), vp.end());
    for (vector<pair<ll, int>>::iterator it = vp.begin(); it != vp.end(); ++it)
    {
        k -= it->second;
        if (k <= 0)
            return it->first;
    }
    return -1LL;
}

ll sum(ll l, ll r, ll ex, ll mod) /* 暴力求和 */
{
    IT itl = split(l), itr = split(r + 1);
    ll res = 0;
    for (; itl != itr; ++itl)
        res = (res + (ll)(itl->r - itl->l + 1) * ksm(itl->w, ex, mod)) % mod;
    return res;
}

int main()
{
    n = read();
    m = read();
    seed = read();
    vmax = read();
    for (int i = 1; i <= n; ++i)
    {
        a[i] = (rnd() % vmax) + 1;
        s.insert(node(i, i, a[i]));
    }
    s.insert(node(n + 1, n + 1, 0));

    for (int i = 1; i <= m; ++i)
    {
        ll op = 1LL * (rnd() % 4) + 1;
        ll l = 1LL * (rnd() % n) + 1;
        ll r = 1LL * (rnd() % n) + 1;
        if (l > r)
            swap(l, r);
        ll x, y;
        if (op == 3)
            x = 1LL * (rnd() % (r - l + 1)) + 1;
        else
            x = 1LL * (rnd() % vmax) + 1;
        if (op == 4)
            y = 1LL * (rnd() % vmax) + 1;
        if (op == 1)
            add(l, r, x);
        else if (op == 2)
            assign(l, r, x);
        else if (op == 3)
            printf("%lld\n", rnk(l, r, x));
        else
            printf("%lld\n", sum(l, r, x, y));
    }
    return 0;
}
posted @ 2021-06-29 09:59  EdisonBa  阅读(59)  评论(0编辑  收藏  举报