• BZOJ1798[Ahoi2009]Seq 维护序列seq 题解


    题目大意:

      有长为N的数列,有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。

    思路:

      用线段树来维护当前的值和要加以及乘的值,由于加与乘是有序的,所以要在做子树之前将标记下传(注意顺序),加和乘分开来、合起来处理都可以。

    代码:(当初手抽将1打成l一直RE调了半天才发现)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #define MAX 400000
     5 #define LL long long
     6 using namespace std;
     7 
     8 LL sum[MAX],mul[MAX],add[MAX],mod;
     9 
    10 void up_date(int cur)
    11 {
    12     sum[cur]=(sum[cur<<1]+sum[cur<<1|1])%mod;
    13 }
    14 
    15 void creat(int L,int R,int x,int y,int cur)
    16 {
    17     mul[cur]=1;
    18     add[cur]=0;
    19     sum[cur]+=y;
    20     if (L==R) return;
    21     int mid=L+R>>1;
    22     if (x>mid) creat(mid+1,R,x,y,cur<<1|1);
    23     else creat(L,mid,x,y,cur<<1);
    24     up_date(cur);
    25 }
    26 
    27 void push_down(int cur,int l,int r,int mid)
    28 {
    29     if (mul[cur]==1 && add[cur]==0) return;
    30     mul[cur<<1]=mul[cur<<1]*mul[cur]%mod;
    31     add[cur<<1]=(add[cur<<1]*mul[cur]%mod+add[cur])%mod;
    32     sum[cur<<1]=(sum[cur<<1]*mul[cur]%mod+add[cur]*(LL)(mid-l+1)%mod)%mod;
    33     mul[cur<<1|1]=mul[cur<<1|1]*mul[cur]%mod;
    34     add[cur<<1|1]=(add[cur<<1|1]*mul[cur]%mod+add[cur])%mod;
    35     sum[cur<<1|1]=(sum[cur<<1|1]*mul[cur]%mod+add[cur]*(LL)(r-mid)%mod)%mod;
    36     mul[cur]=1;
    37     add[cur]=0;
    38     return;
    39 }
    40 
    41 void change_mul(int L,int R,int l,int r,int x,int cur)
    42 {
    43     if (L>=l && R<=r)
    44     {
    45         mul[cur]=mul[cur]*(LL)x%mod;
    46         add[cur]=add[cur]*(LL)x%mod;
    47         sum[cur]=sum[cur]*(LL)x%mod;
    48         return;
    49     }
    50     int mid=L+R>>1;
    51     push_down(cur,L,R,mid);
    52     if (l<=mid) change_mul(L,mid,l,r,x,cur<<1);
    53     if (r>mid) change_mul(mid+1,R,l,r,x,cur<<1|1);
    54     up_date(cur);
    55 }
    56 
    57 void change_add(int L,int R,int l,int r,int x,int cur)
    58 {
    59     if (L>=l && R<=r)
    60     {
    61         add[cur]=(add[cur]+(LL)x)%mod;
    62         sum[cur]=(sum[cur]+(LL)(R-L+1)*x%mod)%mod;
    63         return;
    64     }
    65     int mid=L+R>>1;
    66     push_down(cur,L,R,mid);
    67     if (l<=mid) change_add(L,mid,l,r,x,cur<<1);
    68     if (r>mid) change_add(mid+1,R,l,r,x,cur<<1|1);
    69     up_date(cur);
    70 }
    71 
    72 LL ask(int L,int R,int l,int r,int cur)
    73 {
    74     if (L>=l && R<=r) return sum[cur];
    75     int mid=L+R>>1;
    76     LL ans=0;
    77     push_down(cur,L,R,mid);
    78     if (l<=mid) ans=(ans+ask(L,mid,l,r,cur<<1))%mod;
    79     if (r>mid) ans=(ans+ask(mid+1,R,l,r,cur<<1|1))%mod;
    80     up_date(cur);
    81     return ans;
    82 }
    83 
    84 int main()
    85 {
    86     int n,m,a,b,c,i,x;
    87     scanf("%d%lld",&n,&mod);
    88     for (i=1;i<=n;i++) scanf("%d",&a),creat(1,n,i,a%mod,1);
    89     scanf("%d",&m);
    90     for (i=1;i<=m;i++)
    91     {
    92         scanf("%d",&x);
    93         if (x==1) scanf("%d%d%d",&a,&b,&c),change_mul(1,n,a,b,c%mod,1);
    94         if (x==2) scanf("%d%d%d",&a,&b,&c),change_add(1,n,a,b,c%mod,1);
    95         if (x==3) scanf("%d%d",&a,&b),printf("%lld
    ",ask(1,n,a,b,1));
    96     }
    97     return 0;
    98 }
    我一直在繁华的苍凉中徘徊着,用一颗OI的心寻找着生命和宇宙的美妙与玄奥。
  • 相关阅读:
    ThinkPHP5专题
    php截取中文字符串
    跨域/非跨域接口专题
    JS检查输入项是否为手机号码或者固话号码的正则表达式
    TinkPHP去重统计查询
    模型类设计模式
    经典排序方法 python
    leetcode122 买卖股票的最佳时机 python
    找到链表的倒数第k个节点 python
    链表的实现、输出和反向 python
  • 原文地址:https://www.cnblogs.com/HHshy/p/5733943.html
Copyright © 2020-2023  润新知