P4743 [Wind Festival]Energy Center 题解

语文题(

题意:给定 $1\times m$ 矩阵列 $\{a_n\}$,维护单点插入,单点删除,矩阵列长度,区间和。

思路

用平衡树维护之,考虑经典平衡树五问:

节点信息

因为我们写的是 FHQ,所以要记录左右孩子、两个权值、子树大小。

因为要维护区间和,所以要记录子树和。

节点标记 & 下传标记 & 区间修改

没有区间修改,不考虑。

上传信息

正常更新子树大小。子树和 = 左子树和 + 右子树和 + 节点本身矩阵。

于是我们可以写出:

#define F for(int i = 0;i < m;++i)
inline int R()
{
    int r = 0;char c = getchar();while(!isdigit(c)) c = getchar();
    while(isdigit(c)) r = r * 10 + c - '0', c = getchar();return r;
}
void P(int x) {if(x >= 10) P(x / 10);putchar(x % 10 + '0');}
struct T
{
    T *l, *r;int k, s, v[200], q[200];T() : l(0), r(0), k(rand()), s(1)
    {
        memset(v, 0, m << 2);memset(q, 0, m << 2);g =
        R();while(g--) x = R(), y = R(), v[x] = q[x] = y;
    }
    void u()
    {
        s = 1;memcpy(q, v, m << 2);if(l) {F q[i] += l->q[i];
        s += l->s;}if(r) {F q[i] += r->q[i];s += r->s;}
    }
}*r, *a, *b, *c, *s[30];
void S(T *x, int k, T *&a, T *&b)
{
    if(!x) {a = b = 0;return;}if(!k) {a = 0;b = x;return;}
    if(k >= x->s) {a = x;b = 0;return;}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) {a->r = M(a->r, b);a->u();return a;}
    else {b->l = M(a, b->l);b->u();return b;}
}

(可以选择)用笛卡尔树优化建树过程。

for(int i = 1;i <= n;++i, s[l++] = a)
{
    a = new T;k = a->k;p = l;while(l && k < s[l - 1]->k)
    s[--l]->u();if(l < p) a->l = s[l];if(l) s[l - 1]->r = a;
}
while(l) s[--l]->u();r = s[0];

分别处理每种操作。

while(q--)
{
    scanf("%s", o);switch(o[0])
    {
        case 'I': S(r, R(), a, b);r = M(a, M(new T, b));break;
        case 'D': S(r, R() - 1, a, b);S(b, 1, b, c);delete b;r = M(a, c);break;
        case 'Q': if(o[1] == 'A') P(r->s);else {x = R();y = R();S(r, y, a, c);S(a,
        x - 1, a, b);F P(b->q[i]), putchar(' ');r = M(a, M(b, c));}puts("");break;
    }
}

这题做完了。

Code

#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <cstring>
#define F for(int i = 0;i < m;++i)
inline int R()
{
    int r = 0;char c = getchar();while(!isdigit(c)) c = getchar();
    while(isdigit(c)) r = r * 10 + c - '0', c = getchar();return r;
}
void P(int x) {if(x >= 10) P(x / 10);putchar(x % 10 + '0');}
int n, m, q, l, k, p, g, x, y;char o[3];struct T
{
    T *l, *r;int k, s, v[200], q[200];T() : l(0), r(0), k(rand()), s(1)
    {
        memset(v, 0, m << 2);memset(q, 0, m << 2);g =
        R();while(g--) x = R(), y = R(), v[x] = q[x] = y;
    }
    void u()
    {
        s = 1;memcpy(q, v, m << 2);if(l) {F q[i] += l->q[i];
        s += l->s;}if(r) {F q[i] += r->q[i];s += r->s;}
    }
}*r, *a, *b, *c, *s[30];
void S(T *x, int k, T *&a, T *&b)
{
    if(!x) {a = b = 0;return;}if(!k) {a = 0;b = x;return;}
    if(k >= x->s) {a = x;b = 0;return;}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) {a->r = M(a->r, b);a->u();return a;}
    else {b->l = M(a, b->l);b->u();return b;}
}
int main()
{
    n = R();m = R();for(int i = 1;i <= n;++i, s[l++] = a)
    {
        a = new T;k = a->k;p = l;while(l && k < s[l - 1]->k)
        s[--l]->u();if(l < p) a->l = s[l];if(l) s[l - 1]->r = a;
    }
    while(l) s[--l]->u();r = s[0];q = R();while(q--)
    {
        scanf("%s", o);switch(o[0])
        {
            case 'I': S(r, R(), a, b);r = M(a, M(new T, b));break;
            case 'D': S(r, R() - 1, a, b);S(b, 1, b, c);delete b;r = M(a, c);break;
            case 'Q': if(o[1] == 'A') P(r->s);else {x = R();y = R();S(r, y, a, c);S(a,
            x - 1, a, b);F P(b->q[i]), putchar(' ');r = M(a, M(b, c));}puts("");break;
        }
    }
    return puts("end"), 0;
}
posted @ 2022-08-30 17:51  5k_sync_closer  阅读(4)  评论(0编辑  收藏  举报  来源