SP19543 GSS8 - Can you answer these queries VIII 题解
插入删除区间查询,考虑直接在平衡树上维护答案。
设 $u$ 的左子树为 $L$,右子树为 $R$,$u$ 点的权值为 $v$,则对于一个 $k$,$u$ 子树的答案为
$$ \begin{aligned} &\sum a_i\times i^k\\ =&v\times(|L|+1)^k+\sum_L a_i\times i^k+\sum_R a_i\times(|L|+1+i)^k\\ =&v\times(|L|+1)^k+\sum_L a_i\times i^k+\sum_R a_i\sum_{j=0}^k{k\choose j}i^j(|L|+1)^{k-j}\\ =&v\times(|L|+1)^k+\sum_L a_i\times i^k+\sum_{j=0}^k{k\choose j}(|L|+1)^{k-j}\sum_R a_i\times i^j\\ \end{aligned} $$
这样就可以直接合并两棵子树的答案了。
#include <cstdio>
#include <cstdlib>
#define int unsigned
char o;
int n, m, C[15][15], p[300050][15];
struct T
{
T *l, *r;
int v, q[11], k, s;
T(int _) : l(0), r(0), v(_), k(rand()), s(1)
{
for (int i = 0; i <= 10; ++i)
q[i] = _;
}
void u()
{
s = 1;
if (l)
s += l->s;
if (r)
s += r->s;
int z = l ? l->s : 0;
for (int i = 0; i <= 10; ++i)
{
q[i] = v * p[z + 1][i];
if (l)
q[i] += l->q[i];
if (r)
for (int j = 0; j <= i; ++j)
q[i] += C[i][j] * p[z + 1][i - j] * r->q[j];
}
}
} *r, *a, *b, *c;
void S(T *x, int k, T *&a, T *&b)
{
if (!x)
return void(a = b = 0);
int z = x->l ? x->l->s : 0;
if (z >= k)
b = x, S(x->l, k, a, b->l), b->u();
else
a = x, S(x->r, k - z - 1, a->r, b), a->u();
}
T *M(T *a, T *b)
{
if (!a)
return b;
if (!b)
return a;
if (a->k < b->k)
return a->r = M(a->r, b), a->u(), a;
else
return b->l = M(a, b->l), b->u(), b;
}
signed main()
{
C[0][0] = 1;
for (int i = 1; i <= 10; ++i)
{
C[i][0] = 1;
for (int j = 1; j <= i; ++j)
C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
}
for (int i = 0; i <= 3e5; ++i)
for (int j = p[i][0] = 1; j <= 10; ++j)
p[i][j] = p[i][j - 1] * i;
scanf("%u", &n);
for (int i = 1, x; i <= n; ++i)
scanf("%u", &x), r = M(r, new T(x));
scanf("%u", &m);
for (int i = 0, x, y, k; i < m; ++i)
{
scanf(" %c%u", &o, &x);
switch (o)
{
case 'I':
scanf("%u", &y);
S(r, x, a, b);
r = M(a, M(new T(y), b));
break;
case 'D':
S(r, x, a, b);
S(b, 1, b, c);
r = M(a, c);
break;
case 'R':
scanf("%u", &y);
S(r, x, a, b);
S(b, 1, b, c);
r = M(a, M(new T(y), c));
break;
case 'Q':
scanf("%u%u", &y, &k);
S(r, y + 1, a, c);
S(a, x, a, b);
printf("%u\n", b->q[k]);
r = M(a, M(b, c));
break;
}
}
return 0;
}