码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ1798 线段树的标记合并

时间:2016-05-09 15:54:57      阅读:393      评论:0      收藏:0      [点我收藏+]

标签:

我原来准备做方差的。。

结果发现不会维护两个标记。。

就是操作变成一个 a*x+b ,每次维护a , b 即可

加的时候a=1 ,b=v

乘的时候a=v ,b=0

技术分享
  1 #include <cstdio>
  2 const long long Maxn=100010;
  3 
  4 long long a[Maxn],n,P,l,r,c,m,type;
  5 struct Node
  6 {
  7     long long mul,add,sum,len;
  8 }tree[Maxn<<2];
  9 
 10 inline void Change(long long o,long long mul,long long add)
 11 {
 12     tree[o].mul=(tree[o].mul*mul)%P;
 13     tree[o].add=(tree[o].add*mul+add)%P;
 14     tree[o].sum=(tree[o].sum*mul+tree[o].len*add)%P;
 15 }
 16 inline void push_down(long long o)
 17 {
 18     Change(o<<1,tree[o].mul,tree[o].add);
 19     Change(o<<1|1,tree[o].mul,tree[o].add);
 20     tree[o].mul=1; tree[o].add=0;
 21 }
 22 inline void push_up(long long o)
 23 {
 24     tree[o].sum=(tree[o<<1].sum+tree[o<<1|1].sum)%P;
 25     tree[o].len=tree[o<<1].len+tree[o<<1|1].len;
 26 }
 27 void Build(long long o,long long l,long long r)
 28 {
 29     tree[o].mul=1; tree[o].add=0;
 30     if (l==r) {tree[o].sum=a[l]; tree[o].len=1; return;}
 31     long long mid=(l+r)>>1;
 32     Build(o<<1,l,mid),Build(o<<1|1,mid+1,r);
 33     push_up(o);
 34 }
 35 void Mul(long long o,long long l,long long r,long long p,long long q,long long v)
 36 {
 37     if (l==p && r==q)
 38     {
 39         Change(o,v,0);
 40         return;
 41     }
 42     push_down(o);
 43     long long mid=(l+r)>>1;
 44     if (q<=mid) Mul(o<<1,l,mid,p,q,v);
 45     if (p>=mid+1) Mul(o<<1|1,mid+1,r,p,q,v);
 46     if (p<=mid && q>=mid+1) 
 47         Mul(o<<1,l,mid,p,mid,v),Mul(o<<1|1,mid+1,r,mid+1,q,v);
 48     push_up(o);
 49 }
 50 void Add(long long o,long long l,long long r,long long p,long long q,long long v)
 51 {
 52     if (l==p && r==q)
 53     {
 54         Change(o,1,v);
 55         return;
 56     }
 57     push_down(o);
 58     long long mid=(l+r)>>1;
 59     if (q<=mid) Add(o<<1,l,mid,p,q,v);
 60     if (p>=mid+1) Add(o<<1|1,mid+1,r,p,q,v);
 61     if (p<=mid && q>=mid+1) 
 62         Add(o<<1,l,mid,p,mid,v),Add(o<<1|1,mid+1,r,mid+1,q,v);
 63     push_up(o);
 64 }
 65 long long Sum(long long o,long long l,long long r,long long p,long long q)
 66 {
 67     if (l==p && r==q) return tree[o].sum;
 68     long long mid=(l+r)>>1;
 69     push_down(o);
 70     if (q<=mid) return Sum(o<<1,l,mid,p,q);
 71     if (p>=mid+1) return Sum(o<<1|1,mid+1,r,p,q);
 72     if (p<=mid && q>=mid+1) 
 73         return (Sum(o<<1,l,mid,p,mid)+Sum(o<<1|1,mid+1,r,mid+1,q))%P;
 74 }
 75 int main()
 76 {
 77     // freopen("c.in","r",stdin);
 78     scanf("%lld%lld",&n,&P);
 79     for (long long i=1;i<=n;i++) scanf("%lld",&a[i]);
 80     Build(1,1,n);
 81     scanf("%lld",&m);
 82     for (long long i=1;i<=m;i++)
 83     {
 84         scanf("%lld",&type);
 85         if (type==1) 
 86         {
 87             scanf("%lld%lld%lld",&l,&r,&c);
 88             Mul(1,1,n,l,r,c);
 89         }
 90         if (type==2) 
 91         {
 92             scanf("%lld%lld%lld",&l,&r,&c);
 93             Add(1,1,n,l,r,c);
 94         }
 95         if (type==3) 
 96         {
 97             scanf("%lld%lld",&l,&r);
 98             printf("%lld\n",Sum(1,1,n,l,r));
 99         }
100     }
101     return 0;
102 }
线段树

 

BZOJ1798 线段树的标记合并

标签:

原文地址:http://www.cnblogs.com/yyjxx2010xyu/p/5474101.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!