标签:bit 代码 can pac its blog main scanf 题目
题解:
看到这种题目,一看就是线段树
很明显的区间线段树
加法反正不用说
乘法的时候往加法的地方也要翻倍
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=400005; ll p,v,sum_,addv[N],mulv[N],sumv[N],a[N]; int n,m,c,x,y; void pushdown(int o,int l,int l1,int r,int r1) { sumv[o*2]=(sumv[o*2]*mulv[o]+addv[o]*(l1-l+1))%p; sumv[o*2+1]=(sumv[o*2+1]*mulv[o]+addv[o]*(r1-r+1))%p; addv[o*2]=(addv[o*2]*mulv[o]+addv[o])%p; addv[o*2+1]=(addv[o*2+1]*mulv[o]+addv[o])%p; mulv[o*2]=(mulv[o*2]*mulv[o])%p; mulv[o*2+1]=(mulv[o*2+1]*mulv[o])%p; mulv[o]=1; addv[o]=0; } void updatemul(int o,int l,int r) { if(x<=l&&r<=y) { mulv[o]=(mulv[o]*v)%p; addv[o]=(addv[o]*v)%p; sumv[o]=(sumv[o]*v)%p; return ; } int mid=(l+r)>>1; pushdown(o,l,mid,mid+1,r); if(x<=mid)updatemul(o*2,l,mid); if(y>mid)updatemul(o*2+1,mid+1,r); sumv[o]=(sumv[o*2]+sumv[o*2+1])%p; } void updateadd(int o,int l,int r) { if(x<=l&&r<=y) { addv[o]=(addv[o]+v)%p; sumv[o]=(sumv[o]+v*(r-l+1))%p; return ; } int mid=(l+r)>>1; pushdown(o,l,mid,mid+1,r); if(x<=mid)updateadd(o*2,l,mid); if(y>mid)updateadd(o*2+1,mid+1,r); sumv[o]=(sumv[o*2]+sumv[o*2+1])%p; } void create(int o,int l,int r) { addv[o]=0; mulv[o]=1; if(l==r) { sumv[o]=a[l]; return ; } int mid=(l+r)>>1; create(o*2,l,mid); create(o*2+1,mid+1,r); sumv[o]=(sumv[o*2]+sumv[o*2+1])%p; } void query(int o,int l,int r) { if(x<=l&&r<=y) { sum_+=sumv[o]%p; sum_%=p; return ; } int mid=(l+r)>>1; pushdown(o,l,mid,mid+1,r); if(x<=mid)query(o*2,l,mid); if(y>mid)query(o*2+1,mid+1,r); sumv[o]=(sumv[o*2]+sumv[o*2+1])%p; } int main() { scanf("%d%d",&n,&p); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); create(1,1,n); scanf("%d",&m); while (m--) { scanf("%d%d%d",&c,&x,&y); if(c==1) { scanf("%d",&v); updatemul(1,1,n); } if(c==2) { scanf("%d",&v); updateadd(1,1,n); } if(c==3) { sum_=0; query(1,1,n); printf("%lld\n",sum_); } } return 0; }
标签:bit 代码 can pac its blog main scanf 题目
原文地址:http://www.cnblogs.com/xuanyiming/p/7705624.html