zoukankan      html  css  js  c++  java
  • P3373 【模板】线段树 2

    令人心碎的题,尤其是pushdown操作,一定要好好想想

    #include<iostream>
    #include<cstdio>
    
    using namespace std;
    
    #define LL long long
    
    const int N = 100010;
    
    struct Node{
        int l, r;
        LL sum;
        LL add; // lazy1
        LL mul; // lazy2
    }tr[N * 4];
    
    int n, m, q;
    LL w[N];
    
    void pushdown(int u){
        tr[u << 1].sum = (tr[u << 1].sum * tr[u].mul + tr[u].add * (tr[u << 1].r - tr[u << 1].l + 1)) % q;
        tr[u << 1].add = (tr[u << 1].add * tr[u].mul + tr[u].add) % q;    
        tr[u << 1].mul = (tr[u << 1].mul * tr[u].mul) % q;
        
        tr[u << 1 | 1].sum = (tr[u << 1 | 1].sum * tr[u].mul + tr[u].add * (tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1)) % q;
        tr[u << 1 | 1].add = (tr[u << 1 | 1].add * tr[u].mul + tr[u].add) % q;    
        tr[u << 1 | 1].mul = (tr[u << 1 | 1].mul * tr[u].mul) % q;
        
        tr[u].mul = 1;
        tr[u].add = 0;
    }
    
    void pushup(int u){
        tr[u].sum = (tr[u << 1].sum + tr[u << 1 | 1].sum) % q;
    }
    
    void build(int u, int l, int r){
        if(l == r) tr[u] = {l, r, w[l], 0, 1};
        else{
            tr[u] = {l, r, 0, 0, 1};
            int mid = l + r >> 1;
            build(u << 1, l, mid);
            build(u << 1 | 1, mid + 1, r);
            pushup(u);
        }
    }
    
    void modify(int u, int x, LL v){
        if(tr[u].l == tr[u].r) tr[u].sum += v;
        else{
            int mid = tr[u].l + tr[u].r >> 1;
            if(x <= mid) modify(u << 1, x, v);
            else modify(u << 1 | 1, x, v);
        }
    }
    
    LL query(int u, int l, int r){
        if(l <= tr[u].l && r >= tr[u].r) return tr[u].sum;
        
        pushdown(u);
        
        int mid = tr[u].l + tr[u].r >> 1;
        LL sum = 0;
        if(l <= mid) sum = query(u << 1, l, r) % q;
        if(r > mid) sum = (sum + query(u << 1 | 1, l, r)) % q;
        return sum;
    }
    
    void change_add(int u, int l, int r, LL v){
        if(tr[u].l == l && tr[u].r == r){ // 懒就懒在这儿
            int len = r - l + 1;
            tr[u].add = (tr[u].add + v) % q;
            tr[u].sum = (tr[u].sum + len * v) % q;
            return;
        }
        
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if(r <= mid) change_add(u << 1, l, r, v);
        else if(l > mid) change_add(u << 1 | 1, l, r, v);
        else{
            change_add(u << 1, l, mid, v);
            change_add(u << 1 | 1, mid + 1, r, v);
        }
        pushup(u);
    }
    
    void change_mul(int u, int l, int r, LL v){
        if(tr[u].l == l && tr[u].r == r){
            tr[u].add = tr[u].add * v % q;
            tr[u].mul = tr[u].mul * v % q;
            tr[u].sum = tr[u].sum * v % q;
            return;
        }
        
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if(r <= mid) change_mul(u << 1, l, r, v);
        else if(l > mid) change_mul(u << 1 | 1, l, r, v);
        else{
            change_mul(u << 1, l, mid, v);
            change_mul(u << 1 | 1, mid + 1, r, v);
        }
        pushup(u);
    }
    
    
    int main(){
        cin >> n >> m >> q;
        
        for(int i = 1; i <= n; i ++) scanf("%lld", &w[i]);
        
        build(1, 1, n);
        
        while(m --){
            int k, x, y;
            LL v;
            cin >> k >> x >> y;
            
            if(k == 1){
                cin >> v;
                change_mul(1, x, y, v);
            }else if(k == 2){
                cin >> v;
                change_add(1, x, y, v);
            }else
                cout << query(1, x, y) << endl;
        }
        
        return 0;
    }
    
  • 相关阅读:
    linux命令练习
    Centos修改用户密码
    Git使用
    使用SecureCRT连接虚拟机中Linux系统 和 虚拟机网络配置
    CentOS里Tomcat端口开放
    Linux下安装Tomcat
    laravel 中将DB::select 得到的内容转为数组
    nginx 转发 由于php语法错误 导致的 50x
    windows 下后台启动 redis
    sublime 非常好用的注释工具
  • 原文地址:https://www.cnblogs.com/tomori/p/13762569.html
Copyright © 2011-2022 走看看