线段树 BZOJ1798 [Ahoi2009]Seq 维护序列seq

1798: [Ahoi2009]Seq 维护序列seq

Time Limit: 30 Sec  Memory Limit: 64 MB
Submit: 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

Sample Output

2
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 }
原文地址:https://www.cnblogs.com/zwube/p/7048876.html