线段树+由%加快(CF438D The Child and Sequence

https://www.luogu.org/problem/CF438D

题意

给定数列,区间查询和,区间取模,单点修改。

n,m小于10^5

分析

和花神那题一样,i%k运算可以考虑, i < k时, i不变,所以我们可以维护区间最大值,在给区间[l,r]中的每个元素%k的时候,只要max < k, 就直接return, 由此提速

(提醒: 千万不要用前一题(指花神)的思路解析后一题, 即使他们的做法很相像,但是也要认真写,认真想....我一开始居然维护的是这个区间中每个元素是不是全为0....这个受了花神那题的影响,不是正解, 这样会TLE

(注意: 在计算的时候一定要把long long 啊, int强制转换啊,对应好

#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 190000+99
#define ll long long

int n,m;
ll a[MAX];
struct node{
    ll sum, mx;
}tr[MAX<<2];

void push_up(int o) {
    tr[o].sum = tr[o<<1].sum + tr[o<<1|1].sum ;
    tr[o].mx = max(tr[o<<1].mx , tr[o<<1|1].mx );
}
void build(int o, int l, int r) {
    if(l == r) {
        tr[o].sum = a[l];
        tr[o].mx = a[l];
        return ;
    }
    int mid = (l+r)>>1;
    build(o<<1, l, mid);
    build(o<<1|1, mid+1, r);
    push_up(o);
} 

void update(int o, int l, int r, int x, int v) {
    if(l == r) {
        tr[o].sum = (ll)v;
        tr[o].mx = (ll)v;
        return ;
    }
    int mid = (l+r)>>1;
    if(x <= mid) update(o<<1, l, mid, x, v);
    else update(o<<1|1, mid+1, r, x, v);
    push_up(o);
}

void optmo(int o, int l, int r, int ql, int qr, int k) {
    if(tr[o].mx < k) return ;
    if(l == r) {
        tr[o].sum = tr[o].sum % k;
        tr[o].mx = tr[o].mx % k;
        return ;
    }
    int mid = (l+r)>>1;
    if(ql <= mid) optmo(o<<1, l, mid, ql, qr, k);
    if(mid < qr) optmo(o<<1|1, mid+1, r, ql, qr, k);
    push_up(o);
}

ll query(int o, int l, int r, int ql, int qr) {
    if(ql <= l && r <= qr) return (ll)tr[o].sum ;
    int mid = (l+r)>>1;
    ll ans = 0;
    if(ql <= mid) ans += query(o<<1, l, mid, ql, qr);
    if(mid < qr) ans += query(o<<1|1, mid+1, r, ql, qr);
    return ans;
}

int main() {
    scanf("%d%d",&n, &m);
    for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    build(1, 1, n); 
    int type, l, r, k, x;
    for(int i = 1; i <= m; i++) {
        scanf("%d",&type);
        if(type == 1) {
            scanf("%d%d",&l, &r);
            printf("%lld\n",query(1, 1, n, l, r));
        } else if(type == 2) {
            scanf("%d%d%d",&l,&r, &k);
            optmo(1, 1, n, l, r, k);
        } else if(type == 3) {
            scanf("%d%d",&k, &x);
            update(1, 1, n, k, x);
        }
    }
}
上一篇:CF438D The Child and Sequence


下一篇:[CF438D]The Child and Sequence【线段树】