zoukankan      html  css  js  c++  java
  • 线段树模板二

    题目描述

    如题,已知一个数列,你需要进行下面三种操作:

    1.将某区间每一个数乘上x

    2.将某区间每一个数加上x

    3.求出某区间每一个数的和

    输入格式

    第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。

    第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

    接下来M行每行包含3或4个整数,表示一个操作,具体如下:

    操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k

    操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k

    操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果

    输出格式

    输出包含若干行整数,即为所有操作3的结果。

    输入输出样例

    输入 #1
    5 5 38
    1 5 4 2 3
    2 1 4 1
    3 2 5
    1 2 4 2
    2 3 5 5
    3 1 4
    输出 #1
    17
    2
    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int maxn=2e5+9;
    struct tree{
        int l,r;
        ll sum,add,mul;
    }a[maxn<<2];
    ll s[maxn],p;
    void update(int k)
    {
        a[k].sum=(a[k<<1].sum+a[k<<1|1].sum)%p;
    }
    void build(int k,int l,int r)
    {
        a[k].l=l,a[k].r=r;
        a[k].add=0;
        a[k].mul=1;
        if(l==r)
        {
            a[k].sum=s[l];return;
        }
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        update(k);
    }
    void pushdown(int k)
    {
        if(a[k].l==a[k].r)
        {
            a[k].add=0;
            a[k].mul=1;
            return;
        }
        int mid=(a[k].l+a[k].r)>>1;
        a[k<<1].sum=(a[k<<1].sum*a[k].mul+a[k].add*(mid-a[k].l+1))%p;
        a[k<<1|1].sum=(a[k<<1|1].sum*a[k].mul+a[k].add*(a[k].r-mid))%p;
        a[k<<1].add=(a[k<<1].add*a[k].mul+a[k].add)%p;
        a[k<<1|1].add=(a[k<<1|1].add*a[k].mul+a[k].add)%p;
        a[k<<1].mul=(a[k<<1].mul*a[k].mul)%p;
        a[k<<1|1].mul=(a[k<<1|1].mul*a[k].mul)%p;
        a[k].add=0;
        a[k].mul=1;
        return;
    }
    void changeplus(int k,int l,int r,int x)
    {
    //    cout<<a[k].sum<<"??"<<endl;
        if(a[k].l>r||a[k].r<l)return;
        if(l<=a[k].l&&r>=a[k].r)
        {
            a[k].sum=(a[k].sum+x*(a[k].r-a[k].l+1))%p;
            a[k].add=(a[k].add+x)%p;
            return;
        }
        pushdown(k);
        int mid=(a[k].l+a[k].r)>>1;
    //    if(l<=mid)
        changeplus(k<<1,l,r,x);
    //    if(r>mid)
        changeplus(k<<1|1,l,r,x);
        update(k);
        return;
    }
    void changemul(int k,int l,int r,int x)
    {
    //    cout<<a[k].sum<<"!!"<<endl;
        if(a[k].l>r||a[k].r<l)return;
        if(l<=a[k].l&&r>=a[k].r)
        {
            a[k].sum=(a[k].sum*x)%p;
            a[k].mul=(a[k].mul*x)%p;
            a[k].add=(a[k].add*x)%p;
            return;
        }
        pushdown(k);
        int mid=(a[k].l+a[k].r)>>1;
    //    if(l<=mid)
        changemul(k<<1,l,r,x);
    //    if(r>mid)
        changemul(k<<1|1,l,r,x);
        update(k);
        return;
    }
    ll query(int k,int l,int r)
    {
        if(r<a[k].l||l>a[k].r)return 0;
        pushdown(k);
        if(l<=a[k].l&&r>=a[k].r)
        {
            return a[k].sum;
        }
        int mid=(a[k].l+a[k].r)>>1;
        ll ans=0;
    //    if(l<=mid)
        ans=(ans+query(k<<1,l,r))%p;
    //    if(r>mid)
        ans=(ans+query(k<<1|1,l,r))%p;
        return ans;
    }
    int main()
    {
        int n,m,i;
        scanf("%d%d%lld",&n,&m,&p);
        for(i=1;i<=n;i++)
        scanf("%lld",&s[i]);
        build(1,1,n);
        while(m--)
        {
            int opt,L,R;
            ll x;
            scanf("%d",&opt);
            if(opt==1)
            {
                scanf("%d%d%lld",&L,&R,&x);
                changemul(1,L,R,x);
            }
            if(opt==2)
            {
                scanf("%d%d%lld",&L,&R,&x);
                changeplus(1,L,R,x);
            }
            if(opt==3)
            {
                scanf("%d%d",&L,&R);
                printf("%lld
    ",query(1,L,R));
            }
        }
    }
    欢迎加我qq1165750856一起玩呀~
  • 相关阅读:
    第三十一章 线程------GIL、线/近程池、异/同步、异步回调
    第三十章 网路编程------线程
    第二十八章 网络编程------Socket
    第二十七章 网络编程
    第二十六章 oop中元类、异常处理
    第二十五章 面向对象------封装、内置函数、反射、动态导入
    第二十四章 面向对象------属性
    Document 对象
    正值表达式
    BOM和DOM
  • 原文地址:https://www.cnblogs.com/HHHEN/p/11724442.html
Copyright © 2011-2022 走看看