BZOJ1798[Ahoi2009]Seq 维护序列seq 题解

题目大意:

  有长为N的数列,有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。

思路:

  用线段树来维护当前的值和要加以及乘的值,由于加与乘是有序的,所以要在做子树之前将标记下传(注意顺序),加和乘分开来、合起来处理都可以。

代码:(当初手抽将1打成l一直RE调了半天才发现)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #define MAX 400000
 5 #define LL long long
 6 using namespace std;
 7 
 8 LL sum[MAX],mul[MAX],add[MAX],mod;
 9 
10 void up_date(int cur)
11 {
12     sum[cur]=(sum[cur<<1]+sum[cur<<1|1])%mod;
13 }
14 
15 void creat(int L,int R,int x,int y,int cur)
16 {
17     mul[cur]=1;
18     add[cur]=0;
19     sum[cur]+=y;
20     if (L==R) return;
21     int mid=L+R>>1;
22     if (x>mid) creat(mid+1,R,x,y,cur<<1|1);
23     else creat(L,mid,x,y,cur<<1);
24     up_date(cur);
25 }
26 
27 void push_down(int cur,int l,int r,int mid)
28 {
29     if (mul[cur]==1 && add[cur]==0) return;
30     mul[cur<<1]=mul[cur<<1]*mul[cur]%mod;
31     add[cur<<1]=(add[cur<<1]*mul[cur]%mod+add[cur])%mod;
32     sum[cur<<1]=(sum[cur<<1]*mul[cur]%mod+add[cur]*(LL)(mid-l+1)%mod)%mod;
33     mul[cur<<1|1]=mul[cur<<1|1]*mul[cur]%mod;
34     add[cur<<1|1]=(add[cur<<1|1]*mul[cur]%mod+add[cur])%mod;
35     sum[cur<<1|1]=(sum[cur<<1|1]*mul[cur]%mod+add[cur]*(LL)(r-mid)%mod)%mod;
36     mul[cur]=1;
37     add[cur]=0;
38     return;
39 }
40 
41 void change_mul(int L,int R,int l,int r,int x,int cur)
42 {
43     if (L>=l && R<=r)
44     {
45         mul[cur]=mul[cur]*(LL)x%mod;
46         add[cur]=add[cur]*(LL)x%mod;
47         sum[cur]=sum[cur]*(LL)x%mod;
48         return;
49     }
50     int mid=L+R>>1;
51     push_down(cur,L,R,mid);
52     if (l<=mid) change_mul(L,mid,l,r,x,cur<<1);
53     if (r>mid) change_mul(mid+1,R,l,r,x,cur<<1|1);
54     up_date(cur);
55 }
56 
57 void change_add(int L,int R,int l,int r,int x,int cur)
58 {
59     if (L>=l && R<=r)
60     {
61         add[cur]=(add[cur]+(LL)x)%mod;
62         sum[cur]=(sum[cur]+(LL)(R-L+1)*x%mod)%mod;
63         return;
64     }
65     int mid=L+R>>1;
66     push_down(cur,L,R,mid);
67     if (l<=mid) change_add(L,mid,l,r,x,cur<<1);
68     if (r>mid) change_add(mid+1,R,l,r,x,cur<<1|1);
69     up_date(cur);
70 }
71 
72 LL ask(int L,int R,int l,int r,int cur)
73 {
74     if (L>=l && R<=r) return sum[cur];
75     int mid=L+R>>1;
76     LL ans=0;
77     push_down(cur,L,R,mid);
78     if (l<=mid) ans=(ans+ask(L,mid,l,r,cur<<1))%mod;
79     if (r>mid) ans=(ans+ask(mid+1,R,l,r,cur<<1|1))%mod;
80     up_date(cur);
81     return ans;
82 }
83 
84 int main()
85 {
86     int n,m,a,b,c,i,x;
87     scanf("%d%lld",&n,&mod);
88     for (i=1;i<=n;i++) scanf("%d",&a),creat(1,n,i,a%mod,1);
89     scanf("%d",&m);
90     for (i=1;i<=m;i++)
91     {
92         scanf("%d",&x);
93         if (x==1) scanf("%d%d%d",&a,&b,&c),change_mul(1,n,a,b,c%mod,1);
94         if (x==2) scanf("%d%d%d",&a,&b,&c),change_add(1,n,a,b,c%mod,1);
95         if (x==3) scanf("%d%d",&a,&b),printf("%lld\n",ask(1,n,a,b,1));
96     }
97     return 0;
98 }

 

我一直在繁华的苍凉中徘徊着,用一颗OI的心寻找着生命和宇宙的美妙与玄奥。
posted @ 2016-08-03 18:11  HHshy  阅读(799)  评论(0编辑  收藏  举报