珂朵莉树
珂朵莉树
神奇的暴力数据结构
\(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;
}