BZOJ 5039: [Jsoi2014]序列维护

5039: [Jsoi2014]序列维护

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 282  Solved: 169
[Submit][Status][Discuss]

Description

JYY 有一个维护数列的任务。 他希望你能够来帮助他完成。
JYY 现在有一个长度为 N 的序列 a1,a2,…,aN,有如下三种操作:
1、 把数列中的一段数全部乘以一个值;
2、 把数列中的一段数全部加上一个值;
3、 询问序列中的一段数的和。
由于答案可能很大,对于每个询问,你只需要告诉 JYY 这个询问的答案对 P
取模的结果即可。

Input

第一行包含两个正整数, N 和 P;
第二行包含 N 个非负整数,从左到右依次为 a1,a2,…,aN。
第三行有一个整数 M,表示操作总数。
接下来 M 行,每行满足如下三种形式之一:
1、“ 1 t g c”(不含引号)。表示把所有满足 t ≤ i ≤ g 的 ai 全部乘以 c;
2、“ 2 t g c”(不含引号)。表示把所有满足 t ≤ i ≤ g 的 ai 全部加上 c;
3、“ 3 t g”(不含引号)。表示询问满足 t ≤ i ≤ g 的 ai 的和对 P 取模的值。
1 ≤ N,M ≤ 10^5, 1 ≤ P, c, ai ≤ 2*10^9, 1 ≤ t ≤ g ≤ N

Output

对于每个以 3 开头的操作,依次输出一行,包含对应的结果。

Sample Input

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

Sample Output

2
35
8
【样例说明】
初始时数列为(1,2,3,4,5,6,7)。
经过第 1 次操作后,数列为(1,10,15,20,25,6,7)。
对第 2 次操作,和为 10+15+20=45,模 43 的结果是 2。
经过第 3 次操作后,数列为(1,10,24,29,34,15,16}
对第 4 次操作,和为 1+10+24=35,模 43 的结果是 35。
对第 5 次操作,和为 29+34+15+16=94,模 43 的结果是 8。
 
 
不就是个线段树模板吗QAQ,然后。。。。。

 

  1 /**************************************************************
  2     Problem: 5039
  3     User: Hammer_cwz_77
  4     Language: C++
  5     Result: Accepted
  6     Time:6100 ms
  7     Memory:10276 kb
  8 ****************************************************************/
  9  
 10 #include<cstdio>
 11 #include<cstring>
 12 #include<cstdlib>
 13 #include<algorithm>
 14 #include<cmath>
 15 using namespace std;
 16 typedef long long LL;
 17 LL mod;
 18 struct node
 19 {
 20     int l,r,lc,rc;
 21     LL c;
 22     LL mul,add;
 23     bool lazy;
 24     node(){lazy=false;}
 25 }tr[210000];int trlen;
 26 int n,m;int x[110000];
 27 void bt(int l,int r)
 28 {
 29     int now=++trlen;
 30     tr[now].l=l;tr[now].r=r;
 31     tr[now].lc=tr[now].rc=-1;tr[now].c=0;
 32     tr[now].mul=1;tr[now].add=0;
 33     if(l==r){tr[now].c=x[l]%mod;return ;}
 34     if(l<r)
 35     {
 36         int mid=(l+r)/2;
 37         tr[now].lc=trlen+1; bt(l,mid);
 38         tr[now].rc=trlen+1; bt(mid+1,r);
 39     }
 40     tr[now].c=tr[tr[now].lc].c+tr[tr[now].rc].c;
 41 }
 42 void lazy(int x)
 43 {
 44     int lc=tr[x].lc,rc=tr[x].rc;
 45     int l=tr[x].l,r=tr[x].r;int mid=(l+r)/2;
 46     if(lc!=-1)
 47     {
 48         tr[lc].c=(tr[lc].c*tr[x].mul)%mod;
 49         tr[lc].c=(tr[lc].c+tr[x].add*(mid-l+1))%mod;
 50         tr[lc].mul=(tr[lc].mul*tr[x].mul)%mod;
 51         tr[lc].add=(tr[lc].add*tr[x].mul)%mod;
 52         tr[lc].add=(tr[lc].add+tr[x].add)%mod;
 53     }
 54     if(rc!=-1)
 55     {
 56         tr[rc].c=(tr[rc].c*tr[x].mul)%mod;
 57         tr[rc].c=(tr[rc].c+tr[x].add*(r-mid))%mod;
 58         tr[rc].mul=(tr[rc].mul*tr[x].mul)%mod;
 59         tr[rc].add=(tr[rc].add*tr[x].mul)%mod;
 60         tr[rc].add=(tr[rc].add+tr[x].add)%mod;
 61     }
 62     tr[x].mul=1;tr[x].add=0;
 63 }
 64 void change_x(int now,int l,int r,LL c)//l~r +c
 65 {
 66     if(tr[now].l==l && tr[now].r==r)
 67     {
 68         tr[now].c=(tr[now].c+(r-l+1)*c)%mod;
 69         tr[now].add=(tr[now].add+c)%mod;
 70         return ;
 71     }
 72     int lc=tr[now].lc,rc=tr[now].rc;
 73     int mid=(tr[now].l+tr[now].r)/2;
 74     lazy(now);
 75     if(r<=mid)change_x(lc,l,r,c);
 76     else if(mid+1<=l)change_x(rc,l,r,c);
 77     else
 78     {
 79         change_x(lc,l,mid,c);
 80         change_x(rc,mid+1,r,c);
 81     }
 82     tr[now].c=(tr[lc].c+tr[rc].c)%mod;
 83 }
 84 void change_a(int now,int l,int r,LL c)//l~r *c
 85 {
 86     if(tr[now].l==l && tr[now].r==r)
 87     {
 88         tr[now].c=(tr[now].c*c)%mod;
 89         tr[now].mul=(tr[now].mul*c)%mod;
 90         tr[now].add=(tr[now].add*c)%mod;
 91         return ;
 92     }
 93     int lc=tr[now].lc,rc=tr[now].rc;
 94     int mid=(tr[now].l+tr[now].r)/2;
 95     lazy(now);
 96     if(r<=mid)change_a(lc,l,r,c);
 97     else if(mid+1<=l)change_a(rc,l,r,c);
 98     else
 99     {
100         change_a(lc,l,mid,c);
101         change_a(rc,mid+1,r,c);
102     }
103     tr[now].c=(tr[lc].c+tr[rc].c)%mod;
104 }
105 LL findsum(int now,int l,int r)
106 {
107     if(tr[now].l==l && tr[now].r==r)
108     {
109         lazy(now);
110         return tr[now].c%mod;
111     }
112     int lc=tr[now].lc,rc=tr[now].rc;
113     int mid=(tr[now].l+tr[now].r)/2;
114     lazy(now);
115     if(r<=mid)return findsum(lc,l,r);
116     else if(mid+1<=l)return findsum(rc,l,r);
117     else return ((findsum(lc,l,mid)%mod+findsum(rc,mid+1,r)%mod)%mod);
118 }
119 int main()
120 {
121     scanf("%d%lld",&n,&mod);
122     for(int i=1;i<=n;i++)scanf("%d",&x[i]);
123     trlen=0;bt(1,n);
124     scanf("%d",&m);
125     while(m--)
126     {
127         int q,t,g;LL c;
128         scanf("%d%d%d",&q,&t,&g);
129         if(q==3){printf("%lld\n",findsum(1,t,g)%mod);continue;}
130         scanf("%lld",&c);
131         if(q==1)change_a(1,t,g,c);
132         else change_x(1,t,g,c);
133     }
134     return 0;
135 }

 

---恢复内容结束---

posted @ 2018-03-11 20:41  Hammer_cwz_77  阅读(167)  评论(0编辑  收藏  举报