維護序列 洛谷線段樹模板題2
1104: 維護序列seq
- Time Limit
- 3000 ms
- Memory Limit
- 512072 KBytes
- Judge
- Standard Judge
- Solved
- 71
- Submit
- 234
Description
老師交給小可可一個維護數列的任務,現在小可可希望你來幫他完成。
有長為NN的數列,不妨設為a1,a2,…,aNa1,a2,…,aN。有如下三種操作形式:
(1)把數列中的一段數全部乘一個值;
(2)把數列中的一段數全部加一個值;
(3)詢問數列中的一段數的和,由於答案可能很大,你只需輸出這個數模PP的值。
PS:本數據為純隨機數據,由菜god友情提供
Input Format
第一行兩個整數NN和P(1≤P≤1000000000)P(1≤P≤1000000000)。
第二行含有NN個非負整數,從左到右依次為a1,a2,…,aNa1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N)(0≤ai≤1000000000,1≤i≤N)。
第三行有一個整數MM,表示操作總數。
從第四行開始每行描述一個操作,輸入的操作有以下三種形式:
操作11:“1 t g c1 t g c”(不含雙引號)。表示把所有滿足t≤i≤gt≤i≤g的aiai改為ai×c(1≤t≤g≤N,0≤c≤1000000000)ai×c(1≤t≤g≤N,0≤c≤1000000000)。
操作22:“2 t g c2 t g c”(不含雙引號)。表示把所有滿足t≤i≤gt≤i≤g的aiai改為ai+c(1≤t≤g≤N,0≤c≤1000000000)
操作33:“3 t g3 t g”(不含雙引號)。詢問所有滿足t≤i≤gt≤i≤g的aiai的和模PP的值 (1≤t≤g≤N)(1≤t≤g≤N)。 同一行相鄰兩數之間用一個空格隔開,每行開頭和末尾沒有多余空格。
Output Format
對每個操作33,按照它在輸入中出現的順序,依次輸出一行一個整數表示詢問結果。
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
Hint
【樣例說明】
初始時數列為(1,2,3,4,5,6,7)
經過第11次操作後,數列為(1,10,15,20,25,6,7)(1,10,15,20,25,6,7)。
對第22次操作,和為10+15+20=4510+15+20=45,模4343的結果是22。
經過第33次操作後,數列為(1,10,24,29,34,15,16)(1,10,24,29,34,15,16)
對第44次操作,和為1+10+24=351+10+24=35,模4343的結果是3535。
對第55次操作,和為29+34+15+16=9429+34+15+16=94,模4343的結果是88。
測試數據規模如下表所示
數據編號 1 2 3 4 5 6 7 8 9 10
N= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000
M= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000
Source
Ahoi2009
#include <stdio.h> #define re register typedef long long LL; inline void read(LL &x) { x=0;char c=getchar(); for(; ‘0‘>c || c>‘9‘; c=getchar()); for(; ‘0‘<=c && c<=‘9‘; c=getchar()) x=(x<<1)+(x<<3)+(c^48); } struct node { LL sum; LL mul,add; }; LL P; LL a[100001]; node *s=new node[400004]; inline void build(LL id,LL l,LL r) { s[id].mul=1; s[id].add=0; if(l==r) { s[id].sum=a[l]; return ; } LL mid=(l+r)>>1; build(id<<1,l,mid); build(id<<1|1,mid+1,r); s[id].sum=(s[id<<1].sum+s[id<<1|1].sum)%P; } inline void pushdown(LL id,LL l,LL r) { LL mid=(l+r)>>1; s[id<<1].sum=((s[id<<1].sum*s[id].mul)+((mid-l+1)*s[id].add))%P; s[id<<1|1].sum=((s[id<<1|1].sum*s[id].mul)+((r-mid)*s[id].add))%P; s[id<<1].mul=(s[id<<1].mul*s[id].mul)%P; s[id<<1|1].mul=(s[id<<1|1].mul*s[id].mul)%P; s[id<<1].add=(s[id<<1].add*s[id].mul+s[id].add)%P; s[id<<1|1].add=(s[id<<1|1].add*s[id].mul+s[id].add)%P; s[id].add=0; s[id].mul=1; } inline void _mul(LL id,LL l,LL r,LL L,LL R,LL w) { if(L<=l && r<=R) { s[id].mul=(s[id].mul*w)%P; s[id].add=(s[id].add*w)%P; s[id].sum=(s[id].sum*w)%P; return ; } pushdown(id,l,r); LL mid=(l+r)>>1; if(L<=mid) _mul(id<<1,l,mid,L,R,w); if(R>mid) _mul(id<<1|1,mid+1,r,L,R,w); s[id].sum=(s[id<<1].sum+s[id<<1|1].sum)%P; } inline void _add(LL id,LL l,LL r,LL L,LL R,LL w) { if(L<=l && r<=R) { s[id].add=(s[id].add+w)%P; s[id].sum=(s[id].sum+w*(r-l+1))%P; return ; } pushdown(id,l,r); LL mid=(l+r)>>1; if(L<=mid) _add(id<<1,l,mid,L,R,w); if(R>mid) _add(id<<1|1,mid+1,r,L,R,w); s[id].sum=(s[id<<1].sum+s[id<<1|1].sum)%P; } inline LL search(LL id,LL l,LL r,LL L,LL R) { if(R<l || r<L) return 0; if(L<=l && r<=R) return s[id].sum; pushdown(id,l,r); LL mid=(l+r)>>1; return (search(id<<1,l,mid,L,R)+search(id<<1|1,mid+1,r,L,R))%P; } int main() { LL N; read(N),read(P); for(re LL i=1; i<=N; ++i) read(a[i]); build(1,1,N); LL M; read(M); for(re LL i=1; i<=M; ++i) { LL Q,T,G; read(Q),read(T),read(G); switch (Q) { case 1 :{ LL C; read(C); _mul(1,1,N,T,G,C); break; } case 2 :{ LL C; read(C); _add(1,1,N,T,G,C); break; } default :{ printf("%lld\n",search(1,1,N,T,G)); break; } } } delete[] s; return 0; }
Ojbk
維護序列 洛谷線段樹模板題2