题目大意

区间取模,区间求和,单点修改。

分析

其实算是一道蛮简单的水题。
首先线段树非常好解决后两个操作,重点在于如何解决区间取模的操作。
一开始想到的是暴力单点修改,但是复杂度就飙到了\(mnlogn\),直接爆炸。
但是重新看到了题目中给出的4s的操作,说明,我们可以优化单点修改的操作。
那么我们顺便维护一下区间的最大值,如果当前的区间的最大值是小于mod数的,那么这个区间内的所有数都是没有必要mod的。
后面随着数据的越来越大,那么就可以剪去不必要的操作。

代码

#include <bits/stdc++.h>
#define ll long long
#define N 100005
using namespace std;
struct segment_tree {
    #define lc (nod << 1)
    #define rc (nod << 1 | 1)
    #define mid ((l + r) >> 1)
    struct node {
        ll s;
        int l, r, mx;
        node() {
            mx = s = 0;
        }
    }tr[N << 2];
    void pushup(int nod) {
        tr[nod].s = tr[lc].s + tr[rc].s;
        tr[nod].mx = max(tr[lc].mx, tr[rc].mx);
    }
    void build(int l, int r, int nod, int *a) {
        tr[nod].l = l, tr[nod].r = r;
        if (l == r) {
            tr[nod].mx = tr[nod].s = a[l];
            return;
        }
        build(l, mid, lc, a);
        build(mid + 1, r, rc, a);
        pushup(nod);
    }
    ll query_sec_sum(int nod, int ql, int qr)  {
        ll res = 0;
        int l = tr[nod].l, r = tr[nod].r;
        if (ql <= l && r <= qr) return tr[nod].s;
        if (ql <= mid) res += query_sec_sum(lc, ql, qr);
        if (qr > mid) res += query_sec_sum(rc, ql, qr);
        return res;
    }
    void update_point(int nod, int k, int val) {
        int l = tr[nod].l, r = tr[nod].r;
        if (l == r) {
            tr[nod].mx = tr[nod].s = val;
            return;
        }
        if (k <= mid) update_point(lc, k, val);
        else update_point(rc, k, val);
        pushup(nod);
    }
    void update_sec_mod(int nod, int ql, int qr, int p) {
        int l = tr[nod].l, r = tr[nod].r;
        if (tr[nod].mx < p) return;
        if (l == r) {
            tr[nod].s %= p;
            tr[nod].mx %= p;
            return;
        }
        if (ql <= mid) update_sec_mod(lc, ql, qr, p);
        if (qr > mid) update_sec_mod(rc, ql, qr, p);
        pushup(nod);
    }
}tr;
int a[N];
int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
    tr.build(1, n, 1, a);
    while(m --) {
        int opt, x, y, z;
        scanf("%d", &opt);
        if (opt == 1) {
            scanf("%d%d", &x, &y);
            printf("%lld\n", tr.query_sec_sum(1, x, y));
        }
        if (opt == 2) {
            scanf("%d%d%d", &x, &y, &z);
            tr.update_sec_mod(1, x, y, z);
        }
        if (opt == 3) {
            scanf("%d%d", &x, &z);
            tr.update_point(1, x, z);
        }
    }
    return 0;
}

[CF438D]The Child and Sequence【线段树】的更多相关文章

  1. CF438D The Child and Sequence 线段树

    给定数列,区间查询和,区间取模,单点修改. n,m小于10^5 ...当区间最值小于模数时,就直接返回就好啦~ #include<cstdio> #include<iostream& ...

  2. Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间取摸

    D. The Child and Sequence Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest ...

  3. Codeforces 438D The Child and Sequence - 线段树

    At the children's day, the child came to Picks's house, and messed his house up. Picks was angry at ...

  4. Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间求和+点修改+区间取模

    D. The Child and Sequence   At the children's day, the child came to Picks's house, and messed his h ...

  5. cf250D. The Child and Sequence(线段树 均摊复杂度)

    题意 题目链接 单点修改,区间mod,区间和 Sol 如果x > mod ,那么 x % mod < x / 2 证明: 即得易见平凡, 仿照上例显然, 留作习题答案略, 读者自证不难. ...

  6. CF(438D) The Child and Sequence(线段树)

    题意:对数列有三种操作: Print operation l, r. Picks should write down the value of . Modulo operation l, r, x. ...

  7. CodeForces 438D The Child and Sequence (线段树 暴力)

    传送门 题目大意: 给你一个序列,要求在序列上维护三个操作: 1)区间求和 2)区间取模 3)单点修改 这里的操作二很讨厌,取模必须模到叶子节点上,否则跑出来肯定是错的.没有操作二就是线段树水题了. ...

  8. Codeforces Round #250 (Div. 1) D. The Child and Sequence (线段树)

    题目链接:http://codeforces.com/problemset/problem/438/D 给你n个数,m个操作,1操作是查询l到r之间的和,2操作是将l到r之间大于等于x的数xor于x, ...

  9. 2016暑假多校联合---Rikka with Sequence (线段树)

    2016暑假多校联合---Rikka with Sequence (线段树) Problem Description As we know, Rikka is poor at math. Yuta i ...

随机推荐

  1. 多线程系列之十一:Two-Phase Termination模式

    一,Two-Phase Termination模式 翻译过来就是:分两阶段终止 二,示例程序 public class CountupTread extends Thread { private lo ...

  2. java依赖的斗争:依赖倒置、控制反转和依赖注入

    控制反转(Inversion Of Controller)的一个著名的同义原则是由Robert C.Martin提出的依赖倒置原则(Dependency Inversion Principle),它的 ...

  3. 994.Contiguous Array 邻近数组

    描述 Given a binary array, find the maximum length of a contiguous subarray with equal number of 0 and ...

  4. 372.Definition of ListNode

    单项列表只能把后一个node中的所有数据copy到当前node再delete后一node. /** * Definition of ListNode * class ListNode { * publ ...

  5. vue二次实战

    vue爬坑之路 npm uninstall 模块名(删除指定模块) https://www.cnblogs.com/wisewrong/p/6255817.html vue快速入门 https://s ...

  6. 深浅copy详解

    一. 前言 在python中,对象的赋值和深浅copy,是有差异的.最终得的值也不同,下面我们就通过几个例子,来看下它们之间的区别. 二. 赋值 list2 = ["jack",2 ...

  7. MyBatis源码分析1 参数映射分析

    首先我们拿出之前的代码,在如图位置打上断点,开始调试 我们规定了一个mapper接口,而调用了mapper接口的getEmpByIdAndLastName,我们并没有实现这个接口,这是因为Mybati ...

  8. 转《在浏览器中使用tensorflow.js进行人脸识别的JavaScript API》

    作者 | Vincent Mühle 编译 | 姗姗 出品 | 人工智能头条(公众号ID:AI_Thinker) [导读]随着深度学习方法的应用,浏览器调用人脸识别技术已经得到了更广泛的应用与提升.在 ...

  9. CDH 6.0.1 集群搭建 「Before install」

    从这一篇文章开始会有三篇文章依次介绍集群搭建 「Before install」 「Process」 「After install」 继上一篇使用 docker 部署单机 CDH 的文章,当我们使用 d ...

  10. linux audit (9)--生成audit报表

    aureport这个命令可以生成一个总结性的柱状图报表,默认情况下,在/var/log/audit目录下的所有日志文件都会生成一个报表,也可以使用如下命令来指定一个不同的文件,aureport opt ...