BZOJ1798 [Ahoi2009]Seq 维护序列seq
Posted ljh2000
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1798 [Ahoi2009]Seq 维护序列seq相关的知识,希望对你有一定的参考价值。
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:BZOJ1798
正解:线段树
解题报告:
考虑在线段树上维护一个乘法和加法标记,为了方便,我们把两个标记变成一个式子:$cx+d$的形式。
对于一次加法操作,我们的二元组相当于是$(1,add*len)$,而乘法操作则是$(c,0)$,这个标记可以直接合并,下传的时候合并一下就好了。
//It is made by ljh2000 //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。 #include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <cstdio> #include <string> #include <queue> #include <cmath> #include <ctime> #define lc root<<1 #define rc root<<1|1 #define rep(i,j,k) for(int i=j;i<=k;i++) #define reg(i,x) for(int i=first[x];i;i=next[i]) using namespace std; typedef long long LL; const int MAXN = 300011; int n,m,p; struct node{ int l,r; LL len,c,d,sum; }a[MAXN*3]; inline void update(int root){ a[root].sum=(a[lc].sum+a[rc].sum)%p; } inline int getint(){ int w=0,q=0; char c=getchar(); while((c<\'0\'||c>\'9\') && c!=\'-\') c=getchar(); if(c==\'-\') q=1,c=getchar(); while (c>=\'0\'&&c<=\'9\') w=w*10+c-\'0\',c=getchar(); return q?-w:w; } inline void build(int root,int l,int r){ a[root].l=l; a[root].r=r; a[root].len=r-l+1; a[root].c=1; a[root].d=0; if(l==r) { a[root].sum=getint(); return ; } int mid=(l+r)>>1; build(lc,l,mid); build(rc,mid+1,r); a[root].sum=a[lc].sum+a[rc].sum; a[root].sum%=p;//!!! } inline void calc(node &q,LL c,LL d){ q.c=q.c*c%p; q.d=(q.d*c%p+d)%p; q.sum=(c/*!!!*/*q.sum%p+d/*!!!*/*q.len%p/*!!!*/)%p; if(q.l==q.r) q.c=1,q.d=0; } inline void pushdown(int root,int l,int r){ if(l==r) { a[root].c=1; a[root].d=0; return ; } if(a[root].c==1 && a[root].d==0) return ; calc(a[lc],a[root].c,a[root].d); calc(a[rc],a[root].c,a[root].d); a[root].c=1; a[root].d=0; } inline void modify(int root,int l,int r,int ql,int qr,LL c,LL d){ pushdown(root,l,r); if(ql<=l && r<=qr) { calc(a[root],c,d); return ; } int mid=(l+r)>>1; if(ql<=mid) modify(lc,l,mid,ql,qr,c,d); if(qr>mid) modify(rc,mid+1,r,ql,qr,c,d); update(root); } inline LL query(int root,int l,int r,int ql,int qr){ pushdown(root,l,r); if(ql<=l && r<=qr) return a[root].sum; int mid=(l+r)>>1; if(ql>mid) return query(rc,mid+1,r,ql,qr); else if(qr<=mid) return query(lc,l,mid,ql,qr); else return ( query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr) )%p; update(root); } inline void work(){ n=getint(); p=getint(); build(1,1,n); m=getint(); int type,l,r; LL cc; while(m--) { type=getint(); l=getint(); r=getint(); if(type==1) { cc=getint(); cc%=p; modify(1,1,n,l,r,cc,0); } else if(type==2) { cc=getint(); cc%=p;modify(1,1,n,l,r,1,cc); } else printf("%lld\\n",query(1,1,n,l,r)); } } int main() { #ifndef ONLINE_JUDGE freopen("1798.in","r",stdin); freopen("1798.out","w",stdout); #endif work(); return 0; } //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
以上是关于BZOJ1798 [Ahoi2009]Seq 维护序列seq的主要内容,如果未能解决你的问题,请参考以下文章
bzoj1798: [Ahoi2009]Seq 维护序列seq(线段树)
BZOJ1798 [Ahoi2009]Seq 维护序列seq
bzoj1798: [Ahoi2009]Seq 维护序列seq(线段树多重标记下传)
bzoj 1798 [Ahoi2009]Seq 维护序列seq(线段树+传标)