CF438D The Child and Sequence

外国人的数据结构题真耿直

唯一有难度的操作就是区间取模,然而这个东西可以暴力弄一下,因为一个数$x$被取模不会超过$logn$次。

证明如下(假设$x Mod   y$):

如果$y \leq \frac{x}{2}$那么$x$取模之后会小于$\frac{x}{2}$,而如果$y > \frac{x}{2}$时,$x$取模之后一定也会小于$\frac{x}{2}$

然后就暴力一个一个取过去就好了,还有一个算是剪枝的优化,我们可以顺便维护一下区间最大值,如果区间最大值都小于当前的模数的话,那么就直接$return$好了。

仍然不会算时间复杂度。

丢个模板。

Code:

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;

const int N = 1e5 + 5;

int n, qn;
ll a[N];

template <typename T>
inline void read(T &X) {
    X = 0;
    char ch = 0;
    T op = 1;
    for(; ch > ‘9‘|| ch < ‘0‘; ch = getchar())
        if(ch == ‘-‘) op = -1;
    for(; ch >= ‘0‘ && ch <= ‘9‘; ch = getchar())
        X = (X << 3) + (X << 1) + ch - 48;
    X *= op;
}

inline ll max(ll x, ll y) {
    return x > y ? x : y;
}

namespace SegT {
    ll s[N << 2], maxn[N << 2];

    #define lc p << 1
    #define rc p << 1 | 1
    #define mid ((l + r) >> 1)

    inline void up(int p) {
        if(p) {
            s[p] = s[lc] + s[rc];
            maxn[p] = max(maxn[lc], maxn[rc]);
        }
    }

    void build(int p, int l, int r) {
        if(l == r) {
            s[p] = maxn[p] = a[l];
            return;
        }

        build(lc, l, mid);
        build(rc, mid + 1, r);
        up(p);
    }

    void modify(int p, int l, int r, int x, ll v) {
        if(x == l && x == r) {
            s[p] = maxn[p] = v;
            return;
        }

        if(x <= mid) modify(lc, l, mid, x, v);
        else modify(rc, mid + 1, r, x, v);
        up(p);
    }

    void doMod(int p, int l, int r, int x, int y, ll v) {
        if(maxn[p] < v) return;
        if(l == r) {
            s[p] %= v, maxn[p] %= v;
            return;
        }

        if(x <= mid) doMod(lc, l, mid, x, y, v);
        if(y > mid) doMod(rc, mid + 1, r, x, y, v);
        up(p);
    } 

    ll query(int p, int l, int r, int x, int y) {
        if(x <= l && y >= r) return s[p];
        ll res = 0LL;
        if(x <= mid) res += query(lc, l, mid, x, y);
        if(y > mid) res += query(rc, mid + 1, r, x, y);
        return res;
    }

} using namespace SegT;

int main() {
    read(n), read(qn);
    for(int i = 1; i <= n; i++) read(a[i]);

    build(1, 1, n);
    for(int op, x, y; qn--; ) {
        read(op);
        if(op == 1) read(x), read(y), printf("%lld\n", query(1, 1, n, x, y));
        if(op == 2) {
            read(x), read(y);
            ll v; read(v);
            doMod(1, 1, n, x, y, v);
        }
        if(op == 3) {
            read(x);
            ll v; read(v);
            modify(1, 1, n, x, v);
        }
    }

    return 0;
}

原文地址:https://www.cnblogs.com/CzxingcHen/p/9529952.html

时间: 2024-08-30 12:47:36

CF438D The Child and Sequence的相关文章

CF438D The Child and Sequence 线段树

给定数列,区间查询和,区间取模,单点修改. n,m小于10^5 ...当区间最值小于模数时,就直接返回就好啦~ #include<cstdio> #include<iostream> #define R register int #define ls (tr<<1) #define rs (tr<<1|1) using namespace std; inline long long g() { register long long ret=0,fix=1;

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 house up. Picks was angry at him. A lot of important things were lost, in particular the favorite sequence of Picks. Fortunately, Picks remembers how to

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

题意:对数列有三种操作: Print operation l,?r. Picks should write down the value of . Modulo operation l,?r,?x. Picks should perform assignment a[i]?=?a[i] mod x for each i (l?≤?i?≤?r). Set operation k,?x. Picks should set the value of a[k] to x (in other words

【CF438D】The Child and Sequence(线段树)

点此看题面 大致题意: 给你一个序列,让你支持区间求和.区间取模.单点修改操作. 区间取模 区间求和和单点修改显然都很好维护吧,难的主要是区间取模. 取模标记无法叠加,因此似乎只能暴力搞? 实际上,我么先考虑一个结论: 一个数\(x\)向一个不大于它的数\(p\)取模,所得结果必然小于\(\frac x2\). 证明: 当\(p\le\frac x2\)时,由于\(x\%p<p\),所以\(x\%p<\frac x2\). 当\(p>\frac x2\)时,由于\(p\le x\),所以

CodeForces 438D The Child and Sequence(线段树)

题目:http://codeforces.com/problemset/problem/438/D 一个数取模n%m,有两种情况. 1.m>n, n%m=n; 2.m<=n, n%m<=n/2; 所以当m>n时,取模操作可以忽略. 每个a[i]最多需要log(a[i])次取模操作变为0,因此我们可以对所有取模进行暴力更新.最多要更新n*log(a[i])次,由于单次更新复杂度为log(n),所以总复杂度为n*logn*log(a[i]). #include <bits/std

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,3操作是将下标为k的数变为x. 注意成段更新的时候,遇到一个区间的最大值还小于x的话就停止更新. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5

codeforces438D The Child and Sequence

题面:codeforces438D 正解:线段树. 这题好像是$picks$出的题,然后无限弱化才上的$cf$.. 区间取模,每个数取模以后至少$/2$,所以暴力搞即可. 证明:若$p<x/2$,那么$x \ mod \ p<x/2$:若$p>x/2$,那么$ x \ mod \ p=x-p<x/2$. 维护一个区间最大值,如果$<p$那么就直接退出,否则把这个区间递归做再取模. 1 //It is made by wfj_2048~ 2 #include <algor

【CodeForces 438D 】The Child and Sequence

题意 要求支持三种操作  1.区间求和  2.单点修改  3.区间取模 分析 问题主要在于区间取模 需要多维护一个区间最大值,当最大值已经小于模数的时候就不需要操作了 [先开始读错题了,写了个区间修改哎我没救了] #include<bits/stdc++.h> using namespace std; #define N 110000 #define ll long long #define lc (p<<1) #define rc (p<<1|1) #define m

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

题意 题目链接 单点修改,区间mod,区间和 Sol 如果x > mod ,那么 x % mod < x / 2 证明: 即得易见平凡, 仿照上例显然, 留作习题答案略, 读者自证不难. 反之亦然同理, 推论自然成立, 略去过程Q.E.D., 由上可知证毕. 然后维护个最大值就做完了.. 复杂度不知道是一个log还是两个log,大概是两个吧(线段树一个+最多改log次.) #include<bits/stdc++.h> #define Pair pair<int, int&g