洛谷 P2023 [AHOI2009]维护序列(bzoj P1798 [Ahoi2009]Seq 维护序列seq)

来源:互联网 发布:angularjs.js 2.0下载 编辑:程序博客网 时间:2024/06/06 07:43

传送门

前天看到这道题觉得线段树水过,准备敲一敲分块。然后就没有然后了wa了十发。今天看到就顺手水了水。。最近被拓展lucas和ahoi2017玩废,我恐怕就是一只咸鱼了。。

注意标记下传要加法标记要先乘再加,然后就没什么了。

代码:

#include<iostream>#include<stdio.h>#define ll long longusing namespace std;const int Maxn=100005;struct node{ll l,r,sum,tag_1,tag_2;}tree[Maxn*4];ll n,p;void build(ll l,ll r,ll rt){tree[rt].l=l;tree[rt].r=r;tree[rt].tag_1=1;if(l==r){scanf("%lld",&tree[rt].sum);return ;}ll mid=(l+r)>>1;build(l,mid,rt<<1);build(mid+1,r,rt<<1|1);tree[rt].sum=(tree[rt<<1].sum+tree[rt<<1|1].sum)%p;}void pushdown(ll rt) {if(tree[rt].tag_1==1&&tree[rt].tag_2==0)return ;ll l=tree[rt].l,r=tree[rt].r,mid=(tree[rt].l+tree[rt].r)>>1;tree[rt<<1].tag_1=(tree[rt<<1].tag_1*tree[rt].tag_1)%p;tree[rt<<1].tag_2=(tree[rt<<1].tag_2*tree[rt].tag_1%p+tree[rt].tag_2)%p;tree[rt<<1].sum=(tree[rt<<1].sum*tree[rt].tag_1%p+tree[rt].tag_2*(mid-l+1))%p;tree[rt<<1|1].tag_1=(tree[rt<<1|1].tag_1*tree[rt].tag_1)%p;tree[rt<<1|1].tag_2=(tree[rt<<1|1].tag_2*tree[rt].tag_1%p+tree[rt].tag_2)%p;tree[rt<<1|1].sum=(tree[rt<<1|1].sum*tree[rt].tag_1%p+tree[rt].tag_2*(r-mid))%p;tree[rt].tag_1=1;tree[rt].tag_2=0; }void Mulity(ll l,ll r,ll lf,ll rf,ll rt,ll c){if(lf<=l&&rf>=r){tree[rt].tag_2=tree[rt].tag_2*c%p;tree[rt].tag_1=tree[rt].tag_1*c%p;tree[rt].sum=tree[rt].sum*c%p;return ;}pushdown(rt);ll mid=(l+r)>>1;if(lf<=mid)Mulity(l,mid,lf,rf,rt<<1,c);if(rf>mid)Mulity(mid+1,r,lf,rf,rt<<1|1,c);tree[rt].sum=(tree[rt<<1].sum+tree[rt<<1|1].sum)%p;}void Add(ll l,ll r,ll lf,ll rf,ll rt,ll c){if(lf<=l&&rf>=r){tree[rt].tag_2=(tree[rt].tag_2+c)%p;tree[rt].sum=(tree[rt].sum+(r-l+1)*c)%p;return ;}pushdown(rt);ll mid=(l+r)>>1;if(lf<=mid)Add(l,mid,lf,rf,rt<<1,c);if(rf>mid)Add(mid+1,r,lf,rf,rt<<1|1,c);tree[rt].sum=(tree[rt<<1].sum+tree[rt<<1|1].sum)%p;}ll query(ll l,ll r,ll lf,ll rf,ll rt){if(lf<=l&&rf>=r)return tree[rt].sum%p;pushdown(rt); ll mid=(l+r)>>1;ll ans=0;if(lf<=mid)ans=(ans+query(l,mid,lf,rf,rt<<1)%p)%p;if(rf>mid)ans=(ans+query(mid+1,r,lf,rf,rt<<1|1)%p)%p;tree[rt].sum=(tree[rt<<1].sum+tree[rt<<1|1].sum)%p;return ans%p;}int main(){scanf("%lld%lld",&n,&p);build(1,n,1);ll m,opt;scanf("%lld",&m);for(int i=1;i<=m;i++){ll l,r,c;scanf("%lld",&opt);if(opt==1){scanf("%lld%lld%lld",&l,&r,&c);Mulity(1,n,l,r,1,c);}if(opt==2){scanf("%lld%lld%lld",&l,&r,&c);Add(1,n,l,r,1,c);}if(opt==3){scanf("%lld%lld",&l,&r);printf("%lld\n",query(1,n,l,r,1));}}return 0;}