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

    我们将sumv[o]sumv[o] 定义成sumv[o]=sumv[o]mult[o]+addv[o]sumv[o] = sumv[o] * mult[o] + addv[o]* 区间长度,
    这样就可以正常进行线段树的更新与查询啦。
    这道题完全提升了我对线段树的认识。

    #include<cstdio>
    using namespace std;
    const int maxn = 100000 + 3;
    long long mod;
    int val[maxn];
    long long sumv[maxn << 2], mult[maxn<<2], addv[maxn<<2];
    inline void push_down(int o,int l,int r)
    {
        int mid = (l + r) >> 1, ls = (o<<1), rs = (o<<1)|1;
        if(mult[o] != 1)
        {
            sumv[ls] = (sumv[ls] * mult[o]) % mod, sumv[rs] = (sumv[rs] * mult[o]) % mod;
            mult[ls] = (mult[ls] * mult[o]) % mod, mult[rs] = (mult[rs] * mult[o]) % mod;
            addv[ls] = (addv[ls] * mult[o]) % mod, addv[rs] = (addv[rs] * mult[o]) % mod;
            mult[o] = 1;
        }
        if(addv[o] != 0)
        {
            if(mid >= l)sumv[ls] = (sumv[ls] + addv[o] * (mid - l + 1)) % mod;
            if(mid + 1 <= r)sumv[rs] = (sumv[rs] + addv[o] * (r - mid)) % mod;
            addv[ls] += addv[o], addv[rs] += addv[o];
            addv[o] = 0;
        }
    }
    void build_Tree(int l,int r,int o)
    {
        if(l > r)return;
        mult[o] = 1;
        if(l == r)
        {
            sumv[o] = val[l] % mod; return;
        }
        int mid = (l + r) >> 1, ls = (o<<1), rs = (o<<1)|1;
        build_Tree(l,mid,ls);
        build_Tree(mid + 1,r,rs);
        sumv[o] = (sumv[ls] + sumv[rs]) % mod;
    }
    void update_mult(int l,int r,int L,int R,int o,int k)
    {
        if(l > r || r < L || l > R)return;
        if(l >= L && r <= R)
        {
            sumv[o] = (sumv[o] * k) % mod;
            addv[o] *= k, mult[o] *= k;
            addv[o] %= mod, mult[o] %= mod;
            return;
        }
        push_down(o,l,r);
        int mid = (l + r) >> 1, ls = (o<<1), rs = (o<<1)|1;
        update_mult(l,mid,L,R,ls,k);
        update_mult(mid + 1,r ,L, R,rs,k);
        sumv[o] = (sumv[ls] + sumv[rs]) % mod;
    }
    void update_add(int l,int r,int L,int R,int o,int k)
    {
        if(l > r || r < L || l > R)return;
        if(l >= L && r <= R)
        {
            sumv[o] = (sumv[o] + k * (r - l + 1)) % mod;
            addv[o] += k;
            return;
        }
        push_down(o,l,r);
        int mid = (l + r) >> 1, ls = (o<<1), rs = (o<<1)|1;
        update_add(l,mid,L,R,ls,k);
        update_add(mid + 1,r ,L, R,rs,k);
        sumv[o] = (sumv[ls] + sumv[rs]) % mod;
    }
    long long query(int l,int r,int L,int R,int o)
    {
        if(l > r || r < L || l > R)return 0;
        if(l >= L && r <= R)return sumv[o];
        push_down(o,l,r);
        int mid = (l + r) >> 1, ls = (o<<1), rs = (o<<1)|1;
        long long tmp = 0;
        tmp += query(l,mid,L,R,ls); 
        tmp += query(mid + 1,r,L,R,rs); 
        tmp %= mod;
        return tmp;
    }
    int main()
    {
       // freopen("in.txt","r",stdin);
        int n,m;
        scanf("%d%d%lld",&n,&m,&mod);
        for(int i = 1;i <= n;++i)scanf("%d",&val[i]);
        build_Tree(1,n,1);
        while(m--)
        {
            int x,y,k,opt;
            scanf("%d%d%d",&opt,&x,&y);
            if(opt <= 2)scanf("%d",&k);
            if(opt == 1)update_mult(1,n,x,y,1,k);
            if(opt == 2)update_add(1,n,x,y,1,k);
            if(opt == 3)printf("%lld
    ",query(1,n,x,y,1));
        }
        return 0;
    }
    
  • 相关阅读:
    作用域链概念介绍
    javascript一个作用域案例分析
    scp 常用命令总结
    Django--redis 保存session
    Django学习笔记之Django ORM Aggregation聚合详解
    Django中defer和only区别
    Django中的prefetch_related()函数优化
    Django 中的select_related函数优化查询
    django annotate()的使用
    服务器settings
  • 原文地址:https://www.cnblogs.com/guangheli/p/9845187.html
Copyright © 2011-2022 走看看