AT_abc256_h [ABC256Ex] I like Query Problem 题解

线段树每个点上维护区间最大值、最小值,

区间除以 x 时,由区间对应的每个节点向下递归到 max=min 的节点,在这些节点上区间推平。

每个节点被除 O(logV) 次后 max=min,所以总复杂度 O(nlognlogV)

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