1798: [Ahoi2009]Seq 维护序列seq
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
双标记线段树
蒟蒻wy表示被输出用的lld坑了一个下午。。。
#include<cstdio> int N,M,L,R; long long P,Mul,Add; long long add[500001]; long long mul[500001]; long long sum[500001]; void Up(int k){ sum[k]=(sum[k*2]+sum[k*2+1])%P; } void Insert(int k,int l,int r){ add[k]=0; mul[k]=1; if (l==r){ scanf("%lld",&sum[k]); sum[k]%=P; return; } int mid=(l+r)/2; Insert(k*2,l,mid); Insert(k*2+1,mid+1,r); Up(k); } void Down(int k,int l,int r){ int mid=(l+r)/2; sum[k*2]=(sum[k*2]*mul[k]+add[k]*(long long)(mid-l+1))%P; sum[k*2+1]=(sum[k*2+1]*mul[k]+add[k]*(long long)(r-mid))%P; mul[k*2]=mul[k*2]*mul[k]%P; mul[k*2+1]=mul[k*2+1]*mul[k]%P; add[k*2]=(add[k*2]*mul[k]+add[k])%P; add[k*2+1]=(add[k*2+1]*mul[k]+add[k])%P; mul[k]=1; add[k]=0; } void Change(int k,int l,int r){ if (r<L||R<l)return; if (L<=l&&r<=R){ sum[k]=(sum[k]*Mul+Add*(r-l+1))%P; mul[k]=mul[k]*Mul%P; add[k]=(add[k]*Mul+Add)%P; return; } Down(k,l,r); int mid=(l+r)/2; Change(k*2,l,mid); Change(k*2+1,mid+1,r); Up(k); } long long Sum(int k,int l,int r){ if (r<L||R<l)return 0; if (L<=l&&r<=R)return sum[k]; Down(k,l,r); int mid=(l+r)/2; long long s=(Sum(k*2,l,mid)+Sum(k*2+1,mid+1,r))%P; Up(k); return s; } int main(){ scanf("%d%lld",&N,&P); Insert(1,1,N); scanf("%d",&M); for (;M--;){ int opt; scanf("%d%d%d",&opt,&L,&R); if (opt==1){ scanf("%lld",&Mul); Add=0; Change(1,1,N); } if (opt==2){ scanf("%lld",&Add); Mul=1; Change(1,1,N); } if (opt==3) printf("%lld\n",Sum(1,1,N)); } }