1597An easy problem C(線段樹)
阿新 • • 發佈:2018-12-30
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)); } } }