[AHOI2009]维护序列
Posted 宣毅鸣
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[AHOI2009]维护序列相关的知识,希望对你有一定的参考价值。
题解:
看到这种题目,一看就是线段树
很明显的区间线段树
加法反正不用说
乘法的时候往加法的地方也要翻倍
代码:
#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; }
以上是关于[AHOI2009]维护序列的主要内容,如果未能解决你的问题,请参考以下文章