线段树 2

题目描述
如题,已知一个数列,你需要进行下面三种操作:
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的结果。
输入输出样例
输入样例#15 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
输出样例#117
2

时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据已经过加强^_^)
题面
 1 #include<iostream>
 2 #include<cstdio>
 3 #define ll long long
 4 using namespace std;
 5 const ll N=100002;
 6 ll n,mod,a[N],add[N*10],mul[N*10],sum[N*10];
 7 ll m,op,x,y,k;
 8 void build(ll o,ll l,ll r)
 9 {
10     mul[o]=1;add[o]=0;
11     if(l==r)
12     {
13         sum[o]=a[l]%mod;
14         return;
15     }
16     ll mid=(l+r)>>1;
17     build(o<<1,l,mid);build(o<<1|1,mid+1,r);
18     sum[o]=(sum[o<<1]+sum[o<<1|1])%mod;
19 }
20 void down(ll o,ll l,ll r,ll mid)
21 {
22     if(add[o]==0 && mul[o]==1) return;
23     add[o<<1]=(add[o<<1]*mul[o]+add[o])%mod;
24     mul[o<<1]=mul[o<<1]*mul[o]%mod;
25     sum[o<<1]=(sum[o<<1]*mul[o]%mod+add[o]*(mid-l+1)%mod)%mod;
26     
27     add[o<<1|1]=(add[o<<1|1]*mul[o]+add[o])%mod;
28     mul[o<<1|1]=mul[o<<1|1]*mul[o]%mod;
29     sum[o<<1|1]=(sum[o<<1|1]*mul[o]+add[o]*(r-(mid+1)+1))%mod;
30     
31     add[o]=0;mul[o]=1;
32 }
33 void Mul(ll o,ll l,ll r,ll x,ll y,ll k)
34 {
35     if(x<=l && y>=r)
36     {
37         add[o]=add[o]%mod*k%mod;
38         sum[o]=sum[o]*k%mod%mod;
39         mul[o]=mul[o]*k%mod;
40         return;
41     }
42     ll mid=(l+r)>>1;
43     down(o,l,r,mid);
44     if(x<=mid) Mul(o<<1,l,mid,x,y,k);
45     if(y>=mid+1) Mul(o<<1|1,mid+1,r,x,y,k);
46     sum[o]=(sum[o<<1]+sum[o<<1|1])%mod;
47 }
48 void Add(ll o,ll l,ll r,ll x,ll y,ll k)
49 {
50     if(x<=l && y>=r)
51     {
52         add[o]=(add[o]+k)%mod;
53         sum[o]=(sum[o]+k*(r-l+1)%mod)%mod;
54         return;
55     }
56     ll mid=(l+r)>>1;
57     down(o,l,r,mid);
58     if(x<=mid) Add(o<<1,l,mid,x,y,k);
59     if(y>=mid+1) Add(o<<1|1,mid+1,r,x,y,k);
60     sum[o]=(sum[o<<1]+sum[o<<1|1])%mod;
61 }
62 ll query(ll o,ll l,ll r,ll x,ll y)
63 {
64     if(x<=l && y>=r) 
65     {
66         return sum[o];
67     }
68     ll tot=0,mid=(l+r)>>1;
69     down(o,l,r,mid);
70     if(x<=mid) tot=(tot+query(o<<1,l,mid,x,y))%mod;
71     if(y>=mid+1) tot=(tot+query(o<<1|1,mid+1,r,x,y))%mod;
72     return tot;
73 }
74 int main()
75 {
76     scanf("%lld%lld%lld",&n,&m,&mod);
77     for(ll i=1;i<=n;++i) scanf("%lld",&a[i]);
78     build(1,1,n);
79     while(m--)
80     {
81         scanf("%lld%lld%lld",&op,&x,&y);
82         if(op==1) 
83         {
84             scanf("%lld",&k);
85             Mul(1,1,n,x,y,k);
86         }
87         if(op==2)
88         {
89             scanf("%lld",&k);
90             Add(1,1,n,x,y,k);
91         }
92         if(op==3) 
93          printf("%lld\n",query(1,1,n,x,y)%mod);
94     }
95     return 0;
96 }

 

posted @ 2018-03-31 19:45  月亮茶  阅读(148)  评论(0编辑  收藏  举报