zoukankan      html  css  js  c++  java
  • 【bzoj1798】[Ahoi2009]Seq 维护序列seq

    大意:一个数组,三个操作,第一种是区间[a,b]每个数乘乘,第二种是区间[a,b]每个数加c,第三种是查询[a,b]区间的和并对p取摸。

    两种操作就不能简单的只往下传标记。每次传乘法标记时,要把加法标记同时乘上乘法标记,例如某个区间先进来一个加法标记add,之后又进来一个乘法标记mul。

    那么结果为(x+add)*mul=x*mul+add*mul。这样向下传标记的时候就相对独立。递归边界更新加法标记之前先乘上该节点的mul,左右儿子down的时候先将儿子的add乘上本节点的mul。

    最后说一下sum,比如本节点的存在加法标记x和乘法标记y,并且是先加上x,再乘上y,则左儿子的sum要更新为(sum+x)*y。由于乘法标记传到本节点的时候更新了加法标记,x =x*y,所以sum[o<<1]=(左区间的长度*x)+sum[o<<1]*y。

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 using namespace std;
      8  
      9 typedef long long LL;
     10  
     11 #define N 100010
     12  
     13 int n,m;
     14 int askd,al,ar,ask;
     15 LL p;
     16   
     17 LL add[N<<2],sum[N<<2],mul[N<<2];
     18  
     19 void pushup(int now)
     20 {
     21     sum[now]=(sum[now<<1]+sum[now<<1|1])%p;
     22 }
     23  
     24 void pushdown(int now,int d)
     25 {
     26     if (add[now]!=0 || mul[now]!=1)
     27     {
     28         mul[now<<1]=mul[now<<1]*mul[now]%p;
     29         mul[now<<1|1]=mul[now<<1|1]*mul[now]%p;
     30         add[now<<1]=(add[now]+add[now<<1]*mul[now])%p;
     31         add[now<<1|1]=(add[now]+add[now<<1|1]*mul[now])%p;
     32         sum[now<<1]=(add[now]*(d-(d>>1))+sum[now<<1]*mul[now])%p;
     33         sum[now<<1|1]=(add[now]*(d>>1)+sum[now<<1|1]*mul[now])%p;
     34         add[now]=0;
     35         mul[now]=1;
     36     }
     37 }
     38  
     39 void build(int nowl,int nowr,int now)
     40 {
     41     sum[now]=0;
     42     mul[now]=1;
     43     if (nowl==nowr)
     44     {
     45         scanf("%lld",&sum[now]);
     46         return ;
     47     }
     48     int mid=(nowl+nowr)>>1;
     49     build(nowl,mid,now<<1);
     50     build(mid+1,nowr,now<<1|1);
     51     pushup(now);
     52 }
     53  
     54 void updata_mul(int nowl,int nowr,int now,int l,int r,int c)
     55 {
     56     if (nowl>=l && nowr<=r)
     57     {
     58         add[now]=add[now]*c%p;
     59         sum[now]=sum[now]*c%p;
     60         mul[now]=mul[now]*c%p;
     61         return ;
     62     }
     63     pushdown(now,nowr-nowl+1);
     64     int mid=(nowl+nowr)>>1;
     65     if (l<=mid)
     66         updata_mul(nowl,mid,now<<1,l,r,c);
     67     if (r>mid)
     68         updata_mul(mid+1,nowr,now<<1|1,l,r,c);
     69     pushup(now);
     70 }
     71  
     72 void updata_add(int nowl,int nowr,int now,int l,int r,int c)
     73 {
     74     if (nowl>=l && nowr<=r)
     75     {
     76         add[now]=(add[now]+c)%p;
     77         sum[now]=(sum[now]+c*(nowr-nowl+1))%p;
     78         return ;
     79     }
     80     pushdown(now,nowr-nowl+1);
     81     int mid=(nowl+nowr)>>1;
     82     if (l<=mid)
     83         updata_add(nowl,mid,now<<1,l,r,c);
     84     if (r>mid)
     85         updata_add(mid+1,nowr,now<<1|1,l,r,c);
     86     pushup(now);
     87 }
     88  
     89 LL query(int nowl,int nowr,int now,int l,int r)
     90 {
     91     LL res(0);
     92     if (nowl>=l && nowr<=r)
     93         return sum[now];
     94     pushdown(now,nowr-nowl+1);
     95     int mid=(nowl+nowr)>>1;
     96     if (l<=mid)
     97         res=(res+query(nowl,mid,now<<1,l,r))%p;
     98     if (r>mid)
     99         res=(res+query(mid+1,nowr,now<<1|1,l,r))%p;
    100     return res;
    101 }
    102  
    103 int main()
    104 {
    105     scanf("%d%lld",&n,&p);
    106     build(1,n,1);
    107     scanf("%d",&m);
    108     while (m--)
    109     {
    110         scanf("%d",&askd);
    111         if (askd==1)
    112         {
    113             scanf("%d%d%d",&al,&ar,&ask);
    114             updata_mul(1,n,1,al,ar,ask);
    115         }
    116         if (askd==2)
    117         {
    118             scanf("%d%d%d",&al,&ar,&ask);
    119             updata_add(1,n,1,al,ar,ask);
    120         }
    121         if (askd==3)
    122         {
    123             scanf("%d%d",&al,&ar);
    124             printf("%lld
    ",query(1,n,1,al,ar));
    125         }
    126     }
    127     return 0;
    128 }
  • 相关阅读:
    JVM010JVM有哪些垃圾收集器
    MySQL005MySQL复制的原理是什么
    MySQL002MVCC解决的问题是什么
    MySQL007MySQL索引结构有哪些,各自的优劣是什么
    JVM011如何解决线上gc频繁的问题
    MySQL003MVCC实现原理是什么
    MySQL004MySQL的隔离级别有哪些
    MySQL006MySQL聚簇索引和非聚簇索引的区别
    MySQL001什么是MVCC
    MySQL008MySQL锁的类型有哪些
  • 原文地址:https://www.cnblogs.com/yangjiyuan/p/5495338.html
Copyright © 2011-2022 走看看