题目
N个数排成一列,有三种操作。1.给一段区间内的每个数乘上一个非负整数。2.给一段区间内的每个数加上一个非负整数.3.询问一段区间的和模上P的值。
Input
第一行两个整数N(1≤N≤100000)表示数的个数,P(1≤P≤1000000000)表示模的值。接下来一行N个整数ai(0≤ai≤1000000000),接下来一行一个整数M(1≤M≤100000)表示操作数量,接下来M行每行描述一个操作。第一种操作描述:1 L R C(0≤C≤1000000000),表示把L到R这段区间每个数乘上一个C。第二种操作描述:2 L R C(0≤C≤1000000000),表示把L到R这段区间每个数加上一个C。第三种操作3 L R 表示询问L到R这段区间内的数的和模上P的值。
Output
对面每个询问,输出对应的答案,每个询问占一行。
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
参考博客:http://blog.csdn.net/m0_37134257/article/details/76474704
题难的就是维护一段的加法,可以开另一个标记,在更新标记时如果 * 前有加的话让加的标记先乘也就是代码中的
ss[root<<1].seg=(ss[root].segg*ss[root<<1].seg+ss[root].seg)%p; |
就这句,神奇的是当先乘时由于加的标记为0就是,乘0 和普通的一样
#include<cstdio>
#include<iostream>
using namespace std;
long long a[100009];
long long p;struct tree
{long long sum;long long segg; //*long long seg; //+
}ss[400009];
inline void pushup(int root)
{ss[root].sum=(ss[root<<1].sum+ss[root<<1|1].sum)%p;
}
inline void pushdown(int root,int l,int r)
{int m=(l+r)>>1;ss[root<<1].seg=(ss[root].segg*ss[root<<1].seg+ss[root].seg)%p;ss[root<<1|1].seg= (ss[root].segg*ss[root<<1|1].seg+ss[root].seg)%p;ss[root<<1].segg*=ss[root].segg;ss[root<<1|1].segg*=ss[root].segg;ss[root<<1].segg%=p;ss[root<<1|1].segg%=p;ss[root<<1].sum=(ss[root<<1].sum*ss[root].segg+(m-l+1)*ss[root].seg)%p;ss[root<<1|1].sum=(ss[root<<1|1].sum*ss[root].segg+(r-m)*ss[root].seg)%p;ss[root].seg=0;ss[root].segg=1;
}
void build(int l,int r,int root)
{ ss[root].seg=0;ss[root].segg=1;if(l==r){ss[root].sum=a[l];return;}int m=(l+r)>>1;build(l,m,root<<1);build(m+1,r,root<<1|1);pushup(root);}
void update(int root,int l,int r,int L,int R,long long val,int op) // op 0 * 1 +
{if(l>=L&&R>=r){if(op){ss[root].sum+=val*(r-l+1);ss[root].seg+=val;ss[root].seg%=p;ss[root].sum%=p;}else{ss[root].sum*=val;ss[root].sum%=p;ss[root].segg*=val;ss[root].segg%=p;ss[root].seg*=val;ss[root].seg%=p;}return;}if(ss[root].seg!=0||ss[root].segg!=1){pushdown(root,l,r);}int m=(l+r)>>1;if(L<=m){update(root<<1,l,m,L,R,val,op);}if(R>m){update(root<<1|1,m+1,r,L,R,val,op);}pushup(root);
}
long long query(int root,int l,int r,int L,int R)
{if(l>=L&&R>=r){return ss[root].sum;}if(ss[root].seg!=0||ss[root].segg!=1){pushdown(root,l,r);}int m=(l+r)>>1;long long sum=0;if(L<=m){sum+=query(root<<1,l,m,L,R);sum%=p;}if(R>m){sum+=query(root<<1|1,m+1,r,L,R);sum%=p;}return sum;}int main()
{ios::sync_with_stdio(false);int n,m;cin>>n>>p;for(int i=1;i<=n;i++){cin>>a[i];}build(1,n,1);cin>>m;while(m--){long long q,w,e,val;cin>>q;if(q==1){ cin>>w>>e>>val;update(1,1,n,w,e,val,0);}else if(q==2){cin>>w>>e>>val;update(1,1,n,w,e,val,1);}else{cin>>w>>e;long long x=query(1,1,n,w,e);cout<<(x%p)<<endl;}}return 0;}
注意要用long long WA了n发,惨~ ~ ~ ~ ~