1. 程式人生 > >1597An easy problem C(線段樹)

1597An easy problem C(線段樹)

An easy problem C

Time Limit: 4000/2000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
 

N個數排成一列,有三種操作。1.給一段區間內的每個數乘上一個非負整數。2.給一段區間內的每個數加上一個非負整數.3.詢問一段區間的和模上P的值。

Input

第一行兩個整數N(1≤N≤100000)表示數的個數,P(1≤P≤1000000000)表示模的值。接下來一行N個整數ai(0≤ai≤1000000000),接下來一行一個整數M(1≤M≤100000)表示運算元量,接下來M行每行描述一個操作。第一種操作描述:1 L R C(0≤C≤1000000000),表示把L到R這段區間每個數乘上一個C。第二種操作描述:2 L R C(0≤C≤1000000000),表示把L到R這段區間每個數加上一個C。第三種操作3 L R 表示詢問L到R這段區間內的數的和模上P的值。

Output

對面每個詢問,輸出對應的答案,每個詢問佔一行。

Sample input and output

Sample Input Sample Output
7 43
1 2 3 4 5 6 7
5
1 2 5 5
3 2 4
2 3 7 9
3 1 3
3 4 7
2
35
8

分清乘與加的先後關係,這題就簡單多了;

對於一個區間,如果要乘,不止要原本的乘val,還要把要加的數也乘上val

                         如果要加,那就無所謂了

#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=100005;
typedef long long ll;
ll t[N<<2],ladd[N<<2],lmul[N<<2],n,p,m;
void build(ll l,ll r,ll rt)
{
    lmul[rt]=1,ladd[rt]=0;
    if(l==r)
    {
        scanf("%lld",&t[rt]);
        return;
    }
    ll m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
     t[rt]=(t[rt<<1]+t[rt<<1|1])%p;
}
void pushdown(ll rt,ll num)
{
    ladd[rt<<1]=(ladd[rt<<1]*lmul[rt]+ladd[rt])%p;
    ladd[rt<<1|1]=(ladd[rt<<1|1]*lmul[rt]+ladd[rt])%p;
    lmul[rt<<1]=(lmul[rt<<1]*lmul[rt])%p;
    lmul[rt<<1|1]=(lmul[rt<<1|1]*lmul[rt])%p;
    t[rt<<1]=(t[rt<<1]*lmul[rt]+(num-num/2)*ladd[rt])%p;
    t[rt<<1|1]=(t[rt<<1|1]*lmul[rt]+(num/2)*ladd[rt])%p;
    ladd[rt]=0;
    lmul[rt]=1;
}
void updata(ll x,ll y,ll l,ll r,ll rt,ll val,ll op)
{
    if(x<=l&&r<=y)
    {
        if(op==1)
        {
            ladd[rt]=(ladd[rt]*val)%p;
            lmul[rt]=(lmul[rt]*val)%p;
            t[rt]=(t[rt]*val)%p;
        }
        else
        {
            ladd[rt]=(ladd[rt]+val);
            t[rt]=(t[rt]+(r-l+1)*val)%p;
        }
        return;
    }
    pushdown(rt,r-l+1);
    ll m=(l+r)>>1;
    if(x<=m)
        updata(x,y,l,m,rt<<1,val,op);
    if(y>m)
        updata(x,y,m+1,r,rt<<1|1,val,op);
    t[rt]=(t[rt<<1]+t[rt<<1|1])%p;
}
ll query(ll x,ll y,ll l,ll r,ll rt)
{
    if(x<=l&&y>=r)
       return t[rt]%p;
    pushdown(rt,r-l+1);
    ll m=(l+r)>>1;
    ll res=0;
    if(x<=m)
        res+=query(x,y,l,m,rt<<1);
     if(y>m)
      res+=query(x,y,m+1,r,rt<<1|1);
        return res%p;
}
int main()
{
    scanf("%lld%lld",&n,&p);
    build(1,n,1);
    scanf("%lld",&m);
    ll x,y,val,op;
    for(ll i=0;i<m;i++)
    {
        scanf("%lld",&op);
        if(op==1)
        {
            scanf("%lld%lld%lld",&x,&y,&val);
            updata(x,y,1,n,1,val,1);
        }
        else if(op==2)
        {
            scanf("%lld%lld%lld",&x,&y,&val);
            updata(x,y,1,n,1,val,2);
        }
        else
        {
            scanf("%lld%lld",&x,&y);
            printf("%lld\n",query(x,y,1,n,1));
        }
    }
}