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

    分块,打标记,维护两个标记:乘的 和 加的。

    每次 区间乘的时候,对 乘标记 和 加标记 都 乘上那个值。

    每次 区间加的时候 对 加标记 加上那个值。

    (ax+b)*v=axv+bv。开 long long。

      1 #include<cstdio>
      2 #include<cmath>
      3 using namespace std;
      4 typedef long long ll;
      5 int n,sum,sz,num[100001],l[350],r[350],x,y,m,op;
      6 ll MOD,a[100001],sumv[350],lzy1[350],lzy2[350],v;
      7 void makeblock()
      8 {
      9     sz=sqrt(n); if(!sz) sz=1;
     10     for(sum=1;sum*sz<n;sum++)
     11       {
     12           l[sum]=r[sum-1]+1; r[sum]=sum*sz;
     13           for(int i=l[sum];i<=r[sum];++i)
     14           {
     15               num[i]=sum;
     16               sumv[sum]=(sumv[sum]+a[i])%MOD;
     17           }
     18       }
     19     l[sum]=r[sum-1]+1; r[sum]=n;
     20     for(int i=l[sum];i<=r[sum];++i)
     21       {
     22           num[i]=sum;
     23           sumv[sum]=(sumv[sum]+a[i])%MOD;
     24       }
     25     for(int i=1;i<=sum;++i) lzy1[i]=1;
     26 }
     27 void pushdown(const int &p)
     28 {
     29     if(lzy1[p]!=1 || lzy2[p])
     30       {
     31           for(int i=l[p];i<=r[p];++i)
     32           a[i]=(a[i]*lzy1[p]+lzy2[p])%MOD;
     33           lzy1[p]=1; lzy2[p]=0;
     34       }
     35 }
     36 void work1(const int &L,const int &R)
     37 {
     38     sumv[num[L]]=0;
     39     for(int i=L;i<=R;++i) a[i]=(a[i]*v)%MOD;
     40     for(int i=l[num[L]];i<=r[num[L]];++i)
     41       sumv[num[L]]=(sumv[num[L]]+a[i])%MOD;
     42 }
     43 void update1()
     44 {
     45     pushdown(num[x]); pushdown(num[y]);
     46     if(num[x]==num[y]) work1(x,y);
     47     else
     48       {
     49           work1(x,r[num[x]]); work1(l[num[y]],y);
     50           for(int i=num[x]+1;i<num[y];++i)
     51             {
     52                 lzy1[i]=(lzy1[i]*v)%MOD;
     53                 lzy2[i]=(lzy2[i]*v)%MOD;
     54                 sumv[i]=(sumv[i]*v)%MOD;
     55             }
     56       }
     57 }
     58 void work2(const int &L,const int &R)
     59 {
     60     for(int i=L;i<=R;++i) a[i]=(a[i]+v)%MOD;
     61     sumv[num[L]]=(sumv[num[L]]+(ll)(R-L+1)*v)%MOD;
     62 }
     63 void update2()
     64 {
     65     pushdown(num[x]); pushdown(num[y]);
     66     if(num[x]==num[y]) work2(x,y);
     67     else
     68       {
     69           work2(x,r[num[x]]); work2(l[num[y]],y);
     70           for(int i=num[x]+1;i<num[y];++i)
     71           {
     72               lzy2[i]=(lzy2[i]+v)%MOD;
     73               sumv[i]=(sumv[i]+(ll)sz*v)%MOD;
     74           }
     75       }
     76 }
     77 void query()
     78 {
     79     pushdown(num[x]); pushdown(num[y]); ll ans=0;
     80     if(num[x]==num[y]) {for(int i=x;i<=y;++i) ans=(ans+a[i])%MOD;}
     81     else
     82       {
     83           for(int i=x;i<=r[num[x]];++i) ans=(ans+a[i])%MOD;
     84           for(int i=l[num[y]];i<=y;++i) ans=(ans+a[i])%MOD;
     85           for(int i=num[x]+1;i<num[y];++i) ans=(ans+sumv[i])%MOD;
     86       } printf("%d
    ",(int)ans);
     87 }
     88 int main()
     89 {
     90     scanf("%d%lld",&n,&MOD);
     91     for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
     92     makeblock(); scanf("%d",&m);
     93     for(;m>0;--m)
     94       {
     95           scanf("%d%d%d",&op,&x,&y);
     96           if(op==1) {scanf("%lld",&v); update1();}
     97           else if(op==2) {scanf("%lld",&v); update2();}
     98           else query();
     99       }
    100     return 0;
    101 }
  • 相关阅读:
    大型网站核心架构因素
    大型网站架构模式
    博客中的文章归档是如何实现的
    Caused by: java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp
    git分支开发的好处
    layui之日期和时间组件
    vue-electron脚手架
    springboot1.5.4 配置druid1.1.0(使用druid-spring-boot-starter)
    Node.js读取文件内容并返回值(非异步)
    C# ftp ListFilesOnServer
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4123516.html
Copyright © 2011-2022 走看看