洛谷P3373 【模板】線段樹 2

題目描述

如題,已知一個數列,你須要進行下面三種操做:node

1.將某區間每個數乘上xios

2.將某區間每個數加上xide

3.求出某區間每個數的和ui

輸入輸出格式

輸入格式:spa

第一行包含三個整數N、M、P,分別表示該數列數字的個數、操做的總個數和模數。code

第二行包含N個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。blog

接下來M行每行包含3或4個整數,表示一個操做,具體以下:get

操做1: 格式:1 x y k 含義:將區間[x,y]內每一個數乘上kio

操做2: 格式:2 x y k 含義:將區間[x,y]內每一個數加上kevent

操做3: 格式:3 x y 含義:輸出區間[x,y]內每一個數的和對P取模所得的結果

輸出格式:

輸出包含若干行整數,即爲全部操做3的結果。

輸入輸出樣例

輸入樣例#1: 
5 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
輸出樣例#1: 
17
2

說明

時空限制:1000ms,128M

數據規模:

對於30%的數據:N<=8,M<=10

對於70%的數據:N<=1000,M<=10000

對於100%的數據:N<=100000,M<=100000

(數據已通過增強^_^)

樣例說明:

故輸出應爲1七、2(40 mod 38=2)

  1 #include<iostream>
  2 #include<cstdio>
  3 using namespace std;
  4 int n,m,p,judge,x,y,k;
  5 long long a[100007];
  6 long long read()
  7 {
  8     long long x=0,f=1;
  9     char ch=getchar();
 10     while(ch>'9'||ch<'0')
 11     {
 12         if(ch=='-')
 13             f=-1;
 14         ch=getchar();
 15     }
 16     while(ch>='0'&&ch<='9')
 17     {
 18         x=x*10+ch-'0';
 19         ch=getchar();
 20     }
 21     return x*f;
 22 }
 23 struct node
 24 {
 25     long long v,mul,add;
 26 } st[400007];
 27 void build(int root, int l, int r)
 28 {
 29     st[root].mul=1;
 30     st[root].add=0;
 31     if(l==r)
 32         st[root].v=a[l];
 33     else
 34     {
 35         int m=(l+r)/2;
 36         build(root*2, l, m);
 37         build(root*2+1, m+1, r);
 38         st[root].v=st[root*2].v+st[root*2+1].v;
 39     }
 40     st[root].v%=p;
 41     return ;
 42 }
 43 void pushdown(int root, int l, int r)
 44 {
 45     int m=(l+r)/2;
 46     st[root*2].v=(st[root*2].v*st[root].mul+st[root].add*(m-l+1))%p;
 47     st[root*2+1].v=(st[root*2+1].v*st[root].mul+st[root].add*(r-m))%p;
 48     st[root*2].mul=(st[root*2].mul*st[root].mul)%p;
 49     st[root*2+1].mul=(st[root*2+1].mul*st[root].mul)%p;
 50     st[root*2].add=(st[root*2].add*st[root].mul+st[root].add)%p;
 51     st[root*2+1].add=(st[root*2+1].add*st[root].mul+st[root].add)%p;
 52     st[root].mul=1;
 53     st[root].add=0;
 54     return ;
 55 }
 56 void up(int root,int stdl,int stdr,int l,int r,long long k)
 57 {
 58     if(r<stdl||stdr<l)
 59         return ;
 60     if(l<=stdl&&stdr<=r)
 61     {
 62         st[root].v=(st[root].v*k)%p;
 63         st[root].mul=(st[root].mul*k)%p;
 64         st[root].add=(st[root].add*k)%p;
 65         return ;
 66     }
 67     pushdown(root, stdl, stdr);
 68     int m=(stdl+stdr)/2;
 69     up(root*2,stdl,m,l,r,k);
 70     up(root*2+1,m+1,stdr,l,r,k);
 71     st[root].v=(st[root*2].v+st[root*2+1].v)%p;
 72     return ;
 73 }
 74 void date(int root,int stdl,int stdr,int l,int r,long long k)
 75 {
 76     if(r<stdl||stdr<l)
 77         return ;
 78     if(l<=stdl&&stdr<=r)
 79     {
 80         st[root].add=(st[root].add+k)%p;
 81         st[root].v=(st[root].v+k*(stdr-stdl+1))%p;
 82         return ;
 83     }
 84     pushdown(root,stdl,stdr);
 85     int m=(stdl+stdr)/2;
 86     date(root*2,stdl,m,l,r,k);
 87     date(root*2+1,m+1,stdr,l,r,k);
 88     st[root].v=(st[root*2].v+st[root*2+1].v)%p;
 89     return ;
 90 }
 91 long long query(int root,int stdl,int stdr,int l,int r)
 92 {
 93     if(r<stdl||stdr<l)
 94         return 0;
 95     if(l<=stdl&&stdr<=r)
 96         return st[root].v;
 97     pushdown(root,stdl,stdr);
 98     int m=(stdl+stdr)/2;
 99     return (query(root*2,stdl,m,l,r)+query(root*2+1,m+1,stdr,l,r))%p;
100 }
101 int main()
102 {
103     n=read(),m=read(),p=read();
104     for(int i=1; i<=n; i++)
105         a[i]=read();
106     build(1,1,n);
107     while(m--)
108     {
109         judge=read();
110         if(judge==1)
111         {
112             x=read(),y=read(),k=read();
113             up(1,1,n,x,y,k);
114         }
115         else if(judge==2)
116         {
117             x=read(),y=read(),k=read();
118             date(1,1,n,x,y,k);
119         }
120         else
121         {
122             x=read(),y=read();
123             printf("%lld\n", query(1,1,n,x,y));
124         }
125     }
126     return 0;
127 }
View Code
相關文章
相關標籤/搜索