1798: [Ahoi2009]Seq 维护序列seq
Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 6479 Solved: 2312
[Submit][Status][Discuss]
Description
老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。
有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式:
(1)把数列中的一段数全部乘一个值;
(2)把数列中的一段数全部加一个值;
(3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。
Input
第一行两个整数N和P(1≤P≤1000000000)。第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N)。第三行有一个整数M,表示操作总数。从第四行开始每行描述一个操作,输入的操作有以下三种形式:
操作1:“1 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai×c (1≤t≤g≤N,0≤c≤1000000000)。
操作2:“2 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai+c (1≤t≤g≤N,0≤c≤1000000000)。
操作3:“3 t g”(不含双引号)。询问所有满足t≤i≤g的ai的和模P的值
(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
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
35
8
HINT
【样例说明】
初始时数列为(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。
测试数据规模如下表所示
数据编号 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
线段树的一个入门题,需要注意的是处理延时标记的时候要先处理乘的,后处理加的
这个举个例子模拟一下就清楚了,防止区间交错
好久不写线段树,调了好久……orz
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n,m; 7 long long dt[100010]; 8 int p; 9 struct data{ 10 long long sum,mark_p,mark_m; 11 }segtree[400010]; 12 void build(int pos,int ll,int rr){ 13 segtree[pos].mark_m=1; 14 if(ll==rr){ 15 segtree[pos].sum=dt[ll]%p; 16 return; 17 } 18 int mid=(ll+rr)>>1; 19 build(2*pos,ll,mid); 20 build(2*pos+1,mid+1,rr); 21 segtree[pos].sum=(segtree[pos<<1].sum+segtree[pos<<1|1].sum)%p; 22 return; 23 } 24 void down(int pos,int ll,int mid,int rr){ 25 if(segtree[pos].mark_m==1&&!segtree[pos].mark_p) return; 26 else{ 27 segtree[pos<<1].mark_p=(segtree[pos<<1].mark_p*segtree[pos].mark_m+segtree[pos].mark_p)%p; 28 segtree[pos<<1|1].mark_p=(segtree[pos<<1|1].mark_p*segtree[pos].mark_m+segtree[pos].mark_p)%p; 29 segtree[pos<<1].mark_m=(segtree[pos<<1].mark_m*segtree[pos].mark_m)%p; 30 segtree[pos<<1|1].mark_m=(segtree[pos<<1|1].mark_m*segtree[pos].mark_m)%p; 31 segtree[pos<<1].sum=(segtree[pos<<1].sum*segtree[pos].mark_m+(mid-ll+1)*segtree[pos].mark_p)%p; 32 segtree[pos<<1|1].sum=(segtree[pos<<1|1].sum*segtree[pos].mark_m+(rr-mid)*segtree[pos].mark_p)%p; 33 segtree[pos].mark_m=1; 34 segtree[pos].mark_p=0; 35 } 36 return; 37 } 38 void change_m(int pl,int pr,int d,int pos,int ll,int rr){ 39 if(pl>rr||pr<ll) return; 40 if(pl<=ll&&pr>=rr){ 41 segtree[pos].mark_m=(segtree[pos].mark_m*d)%p; 42 segtree[pos].mark_p=(segtree[pos].mark_p*d)%p; 43 segtree[pos].sum=(segtree[pos].sum*d)%p; 44 return; 45 } 46 int mid=(ll+rr)>>1; 47 down(pos,ll,mid,rr); 48 if(pl<=mid) change_m(pl,pr,d,pos<<1,ll,mid); 49 if(pr>mid) change_m(pl,pr,d,pos<<1|1,mid+1,rr); 50 segtree[pos].sum=(segtree[pos<<1].sum+segtree[pos<<1|1].sum)%p; 51 return; 52 } 53 void change_p(int pl,int pr,int d,int pos,int ll,int rr){ 54 if(pl>rr||pr<ll) return; 55 if(pl<=ll&&pr>=rr){ 56 segtree[pos].mark_p=(segtree[pos].mark_p+d)%p; 57 segtree[pos].sum=(segtree[pos].sum+(rr-ll+1)*d)%p; 58 return; 59 } 60 int mid=(ll+rr)>>1; 61 down(pos,ll,mid,rr); 62 if(pl<=mid) change_p(pl,pr,d,pos<<1,ll,mid); 63 if(pr>mid) change_p(pl,pr,d,pos<<1|1,mid+1,rr); 64 segtree[pos].sum=(segtree[pos<<1].sum+segtree[pos<<1|1].sum)%p; 65 return; 66 } 67 long long ask(int pl,int pr,int pos,int ll,int rr){ 68 if(pl>rr||pr<ll) return 0; 69 if(pl<=ll&&rr<=pr) return segtree[pos].sum%p; 70 int mid=(ll+rr)>>1; 71 down(pos,ll,mid,rr); 72 return (ask(pl,pr,pos<<1,ll,mid)+ask(pl,pr,pos<<1|1,mid+1,rr))%p; 73 } 74 int main(){ 75 scanf("%d%lld",&n,&p); 76 for(int i=1;i<=n;i++) scanf("%lld",&dt[i]); 77 build(1,1,n); 78 scanf("%d",&m); 79 int od,a,b,c; 80 for(int i=1;i<=m;i++){ 81 scanf("%d",&od); 82 if(od==1){ 83 scanf("%d%d%d",&a,&b,&c); 84 change_m(a,b,c,1,1,n); 85 } 86 if(od==2){ 87 scanf("%d%d%d",&a,&b,&c); 88 change_p(a,b,c,1,1,n); 89 } 90 if(od==3){ 91 scanf("%d%d",&a,&b); 92 printf("%d ",ask(a,b,1,1,n)); 93 } 94 } 95 return 0; 96 }