bzoj 1798 Seq 维护序列seq —— 线段树
Posted zinn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1798 Seq 维护序列seq —— 线段树相关的知识,希望对你有一定的参考价值。
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1798
这题还4A...
注意:cnt 从1开始;各种模 p;乘法标记初始值是 1;可能乘 0。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define mid ((l+r)>>1) using namespace std; typedef long long ll; int const xn=1e5+5; int n,a[xn],cnt,ls[xn<<1],rs[xn<<1],sum[xn<<1],lzy[xn<<1],ml[xn<<1],p; int rd() { int ret=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=0; ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘)ret=(ret<<3)+(ret<<1)+ch-‘0‘,ch=getchar(); return f?ret:-ret; } int upt(int x){while(x>=p)x-=p; while(x<0)x+=p; return x;} void build(int x,int l,int r) { ml[x]=1;// if(l==r){sum[x]=a[l]; return;} ls[x]=++cnt; rs[x]=++cnt; build(ls[x],l,mid); build(rs[x],mid+1,r); sum[x]=upt(sum[ls[x]]+sum[rs[x]]); } void turn(int x,int c){sum[x]=(ll)sum[x]*c%p; lzy[x]=(ll)lzy[x]*c%p; ml[x]=(ll)ml[x]*c%p;} void pushdown(int x,int l,int r) { if(ml[x]!=1)//0 { int v=ml[x]; ml[x]=1;//1 turn(ls[x],v); turn(rs[x],v); } if(lzy[x]) { int v=lzy[x]; lzy[x]=0; sum[ls[x]]=(sum[ls[x]]+(ll)(mid-l+1)*v)%p; lzy[ls[x]]=upt(lzy[ls[x]]+v); sum[rs[x]]=(sum[rs[x]]+(ll)(r-mid)*v)%p; lzy[rs[x]]=upt(lzy[rs[x]]+v); } } void mul(int x,int l,int r,int L,int R,int c) { if(l>=L&&r<=R){turn(x,c); return;} pushdown(x,l,r); if(mid>=L)mul(ls[x],l,mid,L,R,c); if(mid<R)mul(rs[x],mid+1,r,L,R,c); sum[x]=upt(sum[ls[x]]+sum[rs[x]]); } void add(int x,int l,int r,int L,int R,int c) { if(l>=L&&r<=R){sum[x]=(sum[x]+(ll)(r-l+1)*c)%p; lzy[x]=upt(lzy[x]+c); return;} pushdown(x,l,r); if(mid>=L)add(ls[x],l,mid,L,R,c); if(mid<R)add(rs[x],mid+1,r,L,R,c); sum[x]=upt(sum[ls[x]]+sum[rs[x]]); } int query(int x,int l,int r,int L,int R) { if(l>=L&&r<=R)return sum[x]; pushdown(x,l,r); int ret=0; if(mid>=L)ret=upt(ret+query(ls[x],l,mid,L,R)); if(mid<R)ret=upt(ret+query(rs[x],mid+1,r,L,R)); return ret; } int main() { n=rd(); p=rd(); for(int i=1;i<=n;i++)a[i]=rd()%p; build(++cnt,1,n); int m=rd(); for(int i=1,tp,l,r,c;i<=m;i++) { tp=rd(); l=rd(); r=rd(); if(tp==1)c=rd()%p,mul(1,1,n,l,r,c); if(tp==2)c=rd()%p,add(1,1,n,l,r,c); if(tp==3)printf("%d ",query(1,1,n,l,r)); } return 0; }
以上是关于bzoj 1798 Seq 维护序列seq —— 线段树的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ1798 [Ahoi2009]Seq 维护序列seq
bzoj 1798 [Ahoi2009]Seq 维护序列seq(线段树+传标)