P4883 mzf的考验 题解

本题为带翻转 CF242E

思路

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

节点信息

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

注意到有区间异或操作,考虑拆位。记录数组 {qw}qi 表示子树内二进制第 i 位为 1 的数的个数。

注意到有区间求和操作,容易发现子树和为 i=0w2iqi

节点标记

根据题意,记录区间翻转、区间异或标记。

下传标记

发现两个标记没有优先级之分,可以单独考虑。

区间翻转标记和文艺平衡树一样,交换左右子树即可,不解释。

设区间异或标记为 x,令左右子树分别执行

qi{sizeqix 二进制第 i 位为 1qix 二进制第 i 位为 0

即可。记得修改节点本身的权值。

区间修改

区间翻转和文艺平衡树一样,标记取反即可,不解释。

设区间异或的值为 x,执行

qi{sizeqix 二进制第 i 位为 1qix 二进制第 i 位为 0

即可。记得修改节点本身的权值。(与下传标记完全一致)

上传信息

正常更新子树大小。执行 qil.qi+r.qi+[节点本身权值二进制第 i 位为 1] 即可。

于是我们可以写出:

#define G(x) if(x & (1 << i))
#define F for(int i = 0;i < 20;++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;
}
struct T
{
    T *l, *r;int v, k, s, x, q[20];bool f;T(int _) : l(0), r(0), v(_),
    k(rand()), s(1), x(0), f(0) {memset(q, 0, sizeof q);F G(_) q[i] = 1;}
    void u()
    {
        s = 1;memset(q, 0, sizeof q);F G(v) q[i] = 1;
        if(l) {s += l->s;F q[i] += l->q[i];}
        if(r) {s += r->s;F q[i] += r->q[i];}
    }
    void d()
    {
        if(f) {T *t = l;l = r;r = t;if(l) l->f ^= 1;if(r) r->f ^= 1;f = 0;}if(x)
        {
            if(l) {F G(x) l->q[i] = l->s - l->q[i];l->v ^= x;l->x ^= x;}
            if(r) {F G(x) r->q[i] = r->s - r->q[i];r->v ^= x;r->x ^= x;}x = 0;
        }
    }
}*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;}x->d();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->d();a->r = M(a->r, b);a->u();return a;}else
    {b->d();b->l = M(a, b->l);b->u();return b;}
}

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

for(int i = 1;i <= n;++i)
{
    a = new T(R());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;s[l++] = a;
}
while(l) s[--l]->u();r = s[0];

分别处理每种操作。

while(m--)
{
    o = R();x = R();y = R();S(r, y, a, c);S(a, x - 1, a, b);switch(o)
    {
        case 1: b->f ^= 1;break;
        case 2: d = R();F G(d) b->q[i] = b->s - b->q[i];b->v ^= d;b->x ^= d;break;
        case 3: q = 0;F q += b->q[i] * (1ll << i);printf("%lld\n", q);break;
    }
    r = M(a, M(b, c));
}

这题做完了。

Code

#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <cstring>
#define G(x) if(x & (1 << i))
#define F for(int i = 0;i < 20;++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;
}
int n, m, l, k, p, o, x, y, d;long long q;struct T
{
    T *l, *r;int v, k, s, x, q[20];bool f;T(int _) : l(0), r(0), v(_),
    k(rand()), s(1), x(0), f(0) {memset(q, 0, sizeof q);F G(_) q[i] = 1;}
    void u()
    {
        s = 1;memset(q, 0, sizeof q);F G(v) q[i] = 1;
        if(l) {s += l->s;F q[i] += l->q[i];}
        if(r) {s += r->s;F q[i] += r->q[i];}
    }
    void d()
    {
        if(f) {T *t = l;l = r;r = t;if(l) l->f ^= 1;if(r) r->f ^= 1;f = 0;}if(x)
        {
            if(l) {F G(x) l->q[i] = l->s - l->q[i];l->v ^= x;l->x ^= x;}
            if(r) {F G(x) r->q[i] = r->s - r->q[i];r->v ^= x;r->x ^= x;}x = 0;
        }
    }
}*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;}x->d();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->d();a->r = M(a->r, b);a->u();return a;}else
    {b->d();b->l = M(a, b->l);b->u();return b;}
}
int main()
{
    srand(388651);n = R();m = R();for(int i = 1;i <= n;++i)
    {
        a = new T(R());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;s[l++] = a;
    }
    while(l) s[--l]->u();r = s[0];while(m--)
    {
        o = R();x = R();y = R();S(r, y, a, c);S(a, x - 1, a, b);switch(o)
        {
            case 1: b->f ^= 1;break;
            case 2: d = R();F G(d) b->q[i] = b->s - b->q[i];b->v ^= d;b->x ^= d;break;
            case 3: q = 0;F q += b->q[i] * (1ll << i);printf("%lld\n", q);break;
        }
        r = M(a, M(b, c));
    }
    return 0;
}
posted @   Jijidawang  阅读(1)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示