• p2023&bzoj1798 维护序列


    传送门(洛谷)

    传送门(bzoj)

    题目

    老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。

    输入格式:

    第一行两个整数N和P(1≤P≤1000000000)。 第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N)。 第三行有一个整数M,表示操作总数。 从第四行开始每行描述一个操作,输入的操作有以下三种形式: 操作1:“1 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai×c (1≤t≤g≤N,0≤c≤1000000000)。 操作2:“2 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai+c (1≤t≤g≤N,0≤c≤1000000000)。 操作3:“3 t g”(不含双引号)。询问所有满足t≤i≤g的ai的和模P的值 (1≤t≤g≤N)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

    输出格式:

    对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。

    分析

    参见洛谷线段树模板2,lazy标记记录两个值mul和add。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    long long n,m,mod;
    struct node {
          long long sum,add,mul;
    }d[440000];
    inline void build(long long le,long long ri,long long pos,long long wh,long long k){
          d[wh].sum+=k;
          d[wh].mul=1;
          if(le==ri)return;
          long long mid=(le+ri)>>1;
          if(mid>=pos)build(le,mid,pos,wh<<1,k);
            else build(mid+1,ri,pos,(wh<<1)|1,k);
    }
    inline void udm(long long le,long long ri,long long x,long long y,long long wh,long long k){
          if(le>=x&&ri<=y){
              d[wh].mul=d[wh].mul*k%mod;
              d[wh].add=d[wh].add*k%mod;
              d[wh].sum=d[wh].sum*k%mod;
              return;
          }
          long long mid=(le+ri)>>1;
          long long t=d[wh].mul,s=d[wh].add;
          d[wh].mul=1,d[wh].add=0;
          d[wh<<1].mul=d[wh<<1].mul*t%mod;
          d[wh<<1].add=(d[wh<<1].add*t%mod+s)%mod;
          d[wh<<1].sum=(d[wh<<1].sum*t%mod+(mid-le+1)*s%mod)%mod;
          d[(wh<<1)|1].mul=d[(wh<<1)|1].mul*t%mod;
          d[(wh<<1)|1].add=(d[(wh<<1)|1].add*t%mod+s)%mod;
          d[(wh<<1)|1].sum=(d[(wh<<1)|1].sum*t%mod+(ri-mid)*s%mod)%mod;
          if(mid>=x)udm(le,mid,x,y,wh<<1,k);
          if(mid<y)udm(mid+1,ri,x,y,(wh<<1)|1,k);
          d[wh].sum=(d[wh<<1].sum+d[(wh<<1)|1].sum)%mod;
    }
    inline void uda(long long le,long long ri,long long x,long long y,long long wh,long long k){
          if(le>=x&&ri<=y){
              d[wh].add=(d[wh].add+k)%mod;
              d[wh].sum=(d[wh].sum+(ri-le+1)*k%mod)%mod;
              return;
          }
          long long mid=(le+ri)>>1;
          long long t=d[wh].mul,s=d[wh].add;
          d[wh].mul=1,d[wh].add=0;
          d[wh<<1].mul=d[wh<<1].mul*t%mod;
          d[wh<<1].add=(d[wh<<1].add*t%mod+s)%mod;
          d[wh<<1].sum=(d[wh<<1].sum*t%mod+(mid-le+1)*s%mod)%mod;
          d[(wh<<1)|1].mul=d[(wh<<1)|1].mul*t%mod;
          d[(wh<<1)|1].add=(d[(wh<<1)|1].add*t%mod+s)%mod;
          d[(wh<<1)|1].sum=(d[(wh<<1)|1].sum*t%mod+(ri-mid)*s%mod)%mod;
          if(mid>=x)uda(le,mid,x,y,wh<<1,k);
          if(mid<y)uda(mid+1,ri,x,y,(wh<<1)|1,k);
          d[wh].sum=(d[wh<<1].sum+d[(wh<<1)|1].sum)%mod;
    }
    inline long long que(long long le,long long ri,long long x,long long y,long long wh){
          if(le>=x&&ri<=y)return d[wh].sum%mod;
          long long mid=(le+ri)>>1,ans=0;
          long long t=d[wh].mul,s=d[wh].add;
          d[wh].mul=1,d[wh].add=0;
          d[wh<<1].mul=d[wh<<1].mul*t%mod;
          d[wh<<1].add=(d[wh<<1].add*t%mod+s)%mod;
          d[wh<<1].sum=(d[wh<<1].sum*t%mod+(mid-le+1)*s%mod)%mod;
          d[(wh<<1)|1].mul=d[(wh<<1)|1].mul*t%mod;
          d[(wh<<1)|1].add=(d[(wh<<1)|1].add*t%mod+s)%mod;
          d[(wh<<1)|1].sum=(d[(wh<<1)|1].sum*t%mod+(ri-mid)*s%mod)%mod;
          if(mid>=x)ans=(ans+que(le,mid,x,y,wh<<1))%mod;
          if(mid<y)ans=(ans+que(mid+1,ri,x,y,(wh<<1)|1))%mod;
          d[wh].sum=(d[wh<<1].sum+d[(wh<<1)|1].sum)%mod;
          return ans;
    }
    int main()
    {     long long i,j,k,x,y,z;
          scanf("%lld%lld",&n,&mod);
          for(i=1;i<=n;i++){
              scanf("%lld",&x);
            build(1,n,i,1,x);
          }
          scanf("%lld",&m);
          for(i=1;i<=m;i++){
              scanf("%lld",&k);
              if(k==1){
                  scanf("%lld%lld%lld",&x,&y,&z);
                  udm(1,n,x,y,1,z);
              }else if(k==2){
                  scanf("%lld%lld%lld",&x,&y,&z);
                  uda(1,n,x,y,1,z);
              }else {
                  scanf("%lld%lld",&x,&y);
                  printf("%lld
    ",que(1,n,x,y,1));
              }
          }
          return 0;
    }
  • 相关阅读:
    树的直径的两种求法
    2018CCPC吉林赛区(重现赛)部分题解
    2019中国大学生程序设计竞赛-女生专场(重现赛)部分题解C-Function(贪心+优先队列) H-clock(模拟)
    HDU-1693 Eat the Trees(插头DP)
    【巷子】---redux---【react】
    【巷子】---flux---【react】
    【JavaScript算法】---希尔排序
    【JavaScript算法】---快速排序法
    【JavaScript算法】---插入排序
    【深拷贝VS浅拷贝】------【巷子】
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9141758.html
Copyright © 2020-2023  润新知