zoukankan      html  css  js  c++  java
  • 「JSOI2014」序列维护

    「JSOI2014」序列维护

    传送门
    其实这题就是luogu的模板线段树2,之所以要发题解就是因为学到了一种比较NB的 ( ext{update}) 的方式。(参见这题
    我们可以把修改操作统一化,视为 (ax + b) 的形式,然后我们按照原来的套路来维护两个标记,分别代表 (a)(b) ,那么我们的更新就可以这么写:

    inline void f(int p, int atag, int mtag, int l, int r) {
        t[p].sum = (t[p].sum * mtag % P + 1ll * atag * (r - l + 1) % P) % P;
        t[p].atag = (t[p].atag * mtag + atag) % P;
        t[p].mtag = t[p].mtag * mtag % P;
    }
    

    然后我们就只需要写一个维护 (ax + b) 操作的修改就可以了。
    其实我们还可以发现这个东西还可以用于区间赋值 ((a = 0))
    简直很妙有没有
    参考代码:

    #include <cstdio>
    #define rg register
    #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
    typedef long long LL;
    template < class T > inline void read(T& s) {
        s = 0; int f = 0; char c = getchar();
        while ('0' > c || c > '9') f |= c == '-', c = getchar();
        while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
        s = f ? -s : s;
    }
     
    const int _ = 100005;
     
    int n, m; LL P, a[_];
    struct node { LL sum, atag, mtag; } t[_ << 2];
     
    inline int lc(int p) { return p << 1; }
     
    inline int rc(int p) { return p << 1 | 1; }
     
    inline void pushup(int p) { t[p].sum = (t[lc(p)].sum + t[rc(p)].sum) % P; }
     
    inline void f(int p, int atag, int mtag, int l, int r) {
        t[p].sum = (t[p].sum * mtag % P + 1ll * atag * (r - l + 1) % P) % P;
        t[p].atag = (t[p].atag * mtag + atag) % P;
        t[p].mtag = t[p].mtag * mtag % P;
    }
     
    inline void pushdown(int p, int l, int r, int mid) {
        if (t[p].atag != 0 || t[p].mtag != 1) {
            f(lc(p), t[p].atag, t[p].mtag, l, mid);
            f(rc(p), t[p].atag, t[p].mtag, mid + 1, r);
            t[p].atag = 0, t[p].mtag = 1;
        }
    }
     
    inline void build(int p = 1, int l = 1, int r = n) {
        t[p].atag = 0, t[p].mtag = 1;
        if (l == r) { t[p].sum = a[l] % P; return ; }
        int mid = (l + r) >> 1;
        build(lc(p), l, mid), build(rc(p), mid + 1, r), pushup(p);
    }
     
    inline void update(int ql, int qr, LL atag, LL mtag, int p = 1, int l = 1, int r = n) {
        if (ql <= l && r <= qr) return f(p, atag, mtag, l, r);
        int mid = (l + r) >> 1;
        pushdown(p, l, r, mid);
        if (ql <= mid) update(ql, qr, atag, mtag, lc(p), l, mid);
        if (qr > mid) update(ql, qr, atag, mtag, rc(p), mid + 1, r);
        pushup(p);
    }
     
    inline LL query(int ql, int qr, int p = 1, int l = 1, int r = n) {
        if (ql <= l && r <= qr) return t[p].sum;
        int mid = (l + r) >> 1; LL res = 0;
        pushdown(p, l, r, mid);
        if (ql <= mid) res = (res + query(ql, qr, lc(p), l, mid)) % P;
        if (qr > mid) res = (res + query(ql, qr, rc(p), mid + 1, r)) % P;
        return res;
    }
     
    int main() {
    #ifndef ONLINE_JUDGE
        file("cpp");
    #endif
        read(n), read(P);
        for (rg int i = 1; i <= n; ++i) read(a[i]);
        build();
        read(m);
        for (rg int opt, l, r; m--; ) {
            read(opt); LL v;
            if (opt == 3) read(l), read(r), printf("%lld
    ", query(l, r));
            else read(l), read(r), read(v), update(l, r, opt != 2 ? 0 : v, opt != 1 ? 1 : v);
        }
        return 0;
    }
    
  • 相关阅读:
    JAVA中的浅拷贝与深拷贝
    Spring异步-@Async注解
    Spring 事务传播行为的使用
    DecimalFormat的使用
    Java编码问题原因以及解决
    Spring
    [TimLinux] docker CentOS7 入门——容器(1)
    [TimLinux] asciinema Linux终端录制工具嵌入私有web中
    [TimLinux] docker CentOS7安装docker-ce最新版
    [TimLinux] systemd 精通CentOS7系统启动systemd
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/12249903.html
Copyright © 2011-2022 走看看