洛谷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\n",query(1,n,x,y,1));
    }
    return 0;
}
posted @ 2018-09-01 22:55  EM-LGH  阅读(138)  评论(0编辑  收藏  举报