zoukankan      html  css  js  c++  java
  • HDU4578

    Description

    思路

    加、乘、设值是常规操作,主要难点是解决p次方的求和操作。这里用sum数组分别存储1到3次方的求和结果。因为对2次方求和的操作需要1次方求和,对3次方求和的操作需要2次方求和。因此维护好三个值就可以直接套板子。

    线段树区间操作有多种操作时,要注意操作的优先级。在pushdown中,优先级高的操作要优先处理。这里显然优先级设值>乘>加,所以在pushdown中,设值优先对子节点的信息进行更新;其次是乘,加。在更新优先级高的lazy时,也要更新所有优先级比它低的lazy,不要漏了高优先级对低优先级的影响。

    pushdown的功能是传递lazy标记和更新子节点信息,所以在叶子结点的时候不能pushdown。
    为了防止出错,在update中,当找到一个完全覆盖的区间时,由于这个区间可能是叶子结点,所以不应该在这里更新lazy以后pushdown,而是直接更新sum的值和lazy。更新sum值得操作和pushdown更新子节点sum值得操作是一模一样的,所以可以通过检测update和pushdown是否相同判断是否代码写错了。(这题我pushdown忘记更新低优先级的lazy,我是在和update对比以后发现这个错误)

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <map>
    #include <vector>
    #include <queue>
    
    
    using namespace std;
    #define endl '
    '
    typedef long long ll;
    
    const int N = 100000 + 100;
    const int M = 10007;
    
    int lazy[N << 2][3];
    int sum[N << 2][3];
    
    void pushup(int rt) {
        for(int i = 0; i < 3; i++)
            sum[rt][i] = (sum[rt << 1][i] + sum[rt << 1 | 1][i]) % M;
    }
    
    void add(int rt, int len, int val) {
        int a1 = val;
        int a2 = (a1 * a1) % M;
        int a3 = (a2 * a1) % M;
        sum[rt][2] = (sum[rt][2] + 3 * a1 * sum[rt][1] % M + 3 * a2 * sum[rt][0] % M + len * a3 % M) % M;
        sum[rt][1] = (sum[rt][1] + 2 * sum[rt][0] * a1 + len * a2) % M;
        sum[rt][0] = (sum[rt][0] + len * a1) % M;
        
    }
    
    void mul(int rt, int val) {
        int m = val % M;
        for(int i = 0; i < 3; i++) {
            sum[rt][i] = (sum[rt][i] * m) % M;
            m = (m * val) % M;
        }
    }
    
    void change(int rt, int len, int val) {
        int c = val;
        for(int i = 0; i < 3; i++) {
            sum[rt][i] = c * len % M;
            c = c * val % M;
        }
    }
    void pd1(int rt, int llen, int rlen, int val) {
        add(rt << 1, llen, val);
        add(rt << 1 | 1, rlen, val);
    }
    void pd2(int rt, int llen, int rlen, int val) {
        mul(rt << 1, val);
        mul(rt << 1 | 1, val);
    }
    
    void pd3(int rt, int llen, int rlen, int val) {
        change(rt << 1, llen,val);
        change(rt << 1 | 1, rlen, val);
    }
    
    
    void pushdown(int rt, int l, int r) { // type : 1 加 2 乘 3 变
        int len = r - l + 1;
        int llen = (len + 1) >> 1;
        int rlen = len >> 1;
        if(lazy[rt][2]) {
            pd3(rt, llen, rlen, lazy[rt][2]);
            lazy[rt << 1][2] = lazy[rt][2] % M;
            lazy[rt << 1 | 1][2] = lazy[rt][2] % M;
    
            lazy[rt << 1][1] = 1;
            lazy[rt << 1 | 1][1] = 1;
            lazy[rt << 1][0] = 0;
            lazy[rt << 1 | 1][0] = 0;
        }
        if(lazy[rt][1] > 1) {
            pd2(rt, llen, rlen, lazy[rt][1]);
            lazy[rt << 1][1] *= lazy[rt][1];
            lazy[rt << 1][1] %= M;
            lazy[rt << 1 | 1][1] *= lazy[rt][1];
            lazy[rt << 1 | 1][1] %= M;
    
            lazy[rt << 1][0] *= lazy[rt][1];
            lazy[rt << 1][0] %= M;
            lazy[rt << 1 | 1][0] *= lazy[rt][1];
            lazy[rt << 1 | 1][0] %= M;
        }
        if(lazy[rt][0]) {
            pd1(rt, llen, rlen, lazy[rt][0]);
            lazy[rt << 1][0] += lazy[rt][0];
            lazy[rt << 1][0] %= M;
            lazy[rt << 1 | 1][0] += lazy[rt][0];
            lazy[rt << 1 | 1][0] %= M;
        }
        
        lazy[rt][2] = 0;
        lazy[rt][1] = 1;
        lazy[rt][0] = 0;
    }
    
    
    
    void build(int l, int r, int rt) {
        if(l == r) {
            lazy[rt][0] = lazy[rt][2] = 0;
            lazy[rt][1] = 1;
            sum[rt][0] = sum[rt][1] = sum[rt][2] = 0;
        } else {
            lazy[rt][0] = lazy[rt][2] = 0;
            lazy[rt][1] = 1;
            int mid = (l + r) / 2;
            build(l, mid, rt << 1);
            build(mid + 1, r, rt << 1 | 1);
            pushup(rt);
        }
    }
    
    void update(int l, int r, int L, int R,int val, int rt, int type) {
        if(L <= l && R >= r) {
            if(type == 1) {
                add(rt, r - l + 1, val);
                lazy[rt][0] = lazy[rt][0] + val % M;
            } else if(type == 2) {
                mul(rt, val);
                lazy[rt][1] = lazy[rt][1] * val % M;
                lazy[rt][0] = lazy[rt][0] * val % M;
            } else {
                change(rt, r - l + 1, val);
                lazy[rt][2] = val % M;
                lazy[rt][1] = 1;
                lazy[rt][0] = 0;
            }
        } else {
            pushdown(rt, l, r);
            int mid = (l + r) / 2;
            if(L <= mid) update(l, mid, L , R, val, rt << 1, type);
            if(mid < R) update(mid + 1, r, L ,R, val, rt << 1 | 1, type);
            pushup(rt);
        }
    }
    
    
    int query_sum(int l, int r, int L, int R, int rt, int p) {
        if(L <= l && R >= r) {
            return sum[rt][p - 1];
        } else {
            int res = 0;
            int mid = (l +r) / 2;
            pushdown(rt, l, r);
            if(L <= mid) res += query_sum(l, mid, L, R, rt << 1, p);
            if(mid < R) res += query_sum(mid + 1, r, L, R, rt << 1 | 1, p);
            pushup(rt); 
            res %= M;
            return res;
        }
    }
    
    int main() {
        ios::sync_with_stdio(false);
        int t;
        int n, m;
        while(cin >> n >> m) {
            if(n == 0 && m == 0) break;
            build(1, n, 1);
            while(m--) {
                int k, l, r, val;
                cin >> k >> l >> r >> val;
                if(k < 4) update(1, n, l, r, val, 1, k);
                else cout << query_sum(1, n, l, r, 1, val) << endl;
            }
        }
    }
    
  • 相关阅读:
    团队项目01应用场景
    团队项目冲刺第一阶段03
    团队冲刺第一阶段02
    团队冲刺第一阶段01
    基于 Scrapy-redis 的分布式爬虫详细设计
    创建CrawlSpider爬虫简要步骤
    如何将redis中的数据导入到本地MongoDB和MySQL数据库
    远程访问ubuntu下mysql的问题
    vi命令汇总
    Chrome/FireFox处理JSON的插件
  • 原文地址:https://www.cnblogs.com/limil/p/12760238.html
Copyright © 2011-2022 走看看