• 线段树区间取膜438D


    438D - The Child and Sequence

    题面

    长度为n的非负整数数列,3种操作

    1. ([L,R])所有数的和。
    2. ([L,R])中所有数都(mod x)
    3. (a_i)修改为(v)
      (n,m≤100000)

    题解

    对于一段区间,如果取模的数比这段区间所有的数都大,那取模就是没有意义的,就是说,如果取模的数比区间最大的数还大,那么就不用取模了,所以我们在线段树里再记录一个区间最大值

    考虑每次取模,对于每一个数(x),取模(y)(x mod y)的值必然比(y)小,如果(y)小于(frac{x}{2}),那x就变得小于(frac{x}{2}),如果(y)大于(frac{x}{2})(x)剩下的部分也比(frac{x}{2})少,(x)也会变得比(frac{x}{2})

    那么就是说(x)每次取模都会变得比(frac{x}{2})小,就是说,对于一个数(x),有效的取(mod)最多进行(logx)次,一共只会进行(nlogn)次取模,那么就算对所有的数取模,这个时间复杂度都是可以接受的

    那么我们对于每个区间记录一个最大值,如果取模的数大于最大值,就不管,如果小于最大值,就暴力取模

    代码

    struct BIT {
        struct node {
            int l, r;
            long long sum;
            int mx;
        } tr[N << 2];
        void push_up(int p) {
            tr[p].mx = max(tr[p << 1].mx, tr[p << 1 | 1].mx);
            tr[p].sum = tr[p << 1].sum + tr[p << 1 | 1].sum;
        }
        void build(int p, int l, int r, vector<int>& a) {
            tr[p].l = l, tr[p].r = r;
            if (l == r) {
                tr[p].sum = tr[p].mx = a[l];
                return;
            }
            int mid = l + r >> 1;
            build(p << 1, l, mid, a);
            build(p << 1 | 1, mid + 1, r, a);
            push_up(p);
        }
        int ask(int p, int l, int r) {
            if (tr[p].l >= l && tr[p].r <= r)
                return tr[p].sum;
            int mid = tr[p].l + tr[p].r >> 1;
            if (mid >= r)
                return ask(p << 1, l, r);
            if (mid < l)
                return ask(p << 1 | 1, l, r);
            return ask(p << 1, l, r) + ask(p << 1 | 1, l, r);
        }
        void change(int p, int k, int v) {
            if (tr[p].l == k && tr[p].r == k) {
                tr[p].sum = tr[p].mx = v;
                return;
            }
            int mid = tr[p].l + tr[p].r >> 1;
            if (mid >= k)
                change(p << 1, k, v);
            else if (mid < k)
                change(p << 1 | 1, k, v);
            push_up(p);
        }
        void changemod(int p, int l, int r, int mod) {
            if (tr[p].l == tr[p].r) {
                tr[p].sum = tr[p].mx = tr[p].sum % mod;
                return;
            }
            int mid = tr[p].l + tr[p].r >> 1;
            if (mid >= l && tr[p << 1].mx >= mod)
                changemod(p << 1, l, r, mod);
            if (mid < r && tr[p << 1 | 1].mx >= mod)
                changemod(p << 1 | 1, l, r, mod);
            push_up(p);
        }
    } bit;
    
    int main() {
        ios::sync_with_stdio(0);
        cin.tie(0), cout.tie(0);
    
        int n, m;
        cin >> n >> m;
    
        vector<int> a(n + 1);
        for (int i = 1; i <= n; ++i)
            cin >> a[i];
        bit.build(1, 1, n, a);
    
        while (m--) {
            int op;
            cin >> op;
            if (op == 1) {
                int l, r;
                cin >> l >> r;
                cout << bit.ask(1, l, r) << '
    ';
            } else if (op == 2) {
                int l, r, mod;
                cin >> l >> r >> mod;
                bit.changemod(1, l, r, mod);
            } else {
                int k, v;
                cin >> k >> v;
                bit.change(1, k, v);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    shell28获取命令结果的第几个参数
    在 Amazon EC2 Linux 实例上手动安装 SSM 代理 Raspbian
    Trying out the Intel Neural Compute Stick 2 – Movidius NCS2
    Flask
    virtualenv/venv 和 pip
    轻量化卷积神经网络:SqueezeNet、MobileNet、ShuffleNet、Xception
    向 AWS Elastic Beanstalk 部署 Flask 应用程序
    Installing the AWS Toolkit for Visual Studio Code
    Installing the AWS SAM CLI on macOS
    树莓派显示器电源管理禁止屏幕休眠
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/15018954.html
Copyright © 2020-2023  润新知