zoukankan      html  css  js  c++  java
  • BZOJ 5039: [Jsoi2014]序列维护

    5039: [Jsoi2014]序列维护

    Time Limit: 20 Sec  Memory Limit: 256 MB
    Submit: 282  Solved: 169
    [Submit][Status][Discuss]

    Description

    JYY 有一个维护数列的任务。 他希望你能够来帮助他完成。
    JYY 现在有一个长度为 N 的序列 a1,a2,…,aN,有如下三种操作:
    1、 把数列中的一段数全部乘以一个值;
    2、 把数列中的一段数全部加上一个值;
    3、 询问序列中的一段数的和。
    由于答案可能很大,对于每个询问,你只需要告诉 JYY 这个询问的答案对 P
    取模的结果即可。

    Input

    第一行包含两个正整数, N 和 P;
    第二行包含 N 个非负整数,从左到右依次为 a1,a2,…,aN。
    第三行有一个整数 M,表示操作总数。
    接下来 M 行,每行满足如下三种形式之一:
    1、“ 1 t g c”(不含引号)。表示把所有满足 t ≤ i ≤ g 的 ai 全部乘以 c;
    2、“ 2 t g c”(不含引号)。表示把所有满足 t ≤ i ≤ g 的 ai 全部加上 c;
    3、“ 3 t g”(不含引号)。表示询问满足 t ≤ i ≤ g 的 ai 的和对 P 取模的值。
    1 ≤ N,M ≤ 10^5, 1 ≤ P, c, ai ≤ 2*10^9, 1 ≤ t ≤ g ≤ N

    Output

    对于每个以 3 开头的操作,依次输出一行,包含对应的结果。

    Sample Input

    7 43
    1 2 3 4 5 6 7
    5
    1 2 5 5
    3 2 4
    2 3 7 9
    3 1 3
    3 4 7

    Sample Output

    2
    35
    8
    【样例说明】
    初始时数列为(1,2,3,4,5,6,7)。
    经过第 1 次操作后,数列为(1,10,15,20,25,6,7)。
    对第 2 次操作,和为 10+15+20=45,模 43 的结果是 2。
    经过第 3 次操作后,数列为(1,10,24,29,34,15,16}
    对第 4 次操作,和为 1+10+24=35,模 43 的结果是 35。
    对第 5 次操作,和为 29+34+15+16=94,模 43 的结果是 8。
     
     
    不就是个线段树模板吗QAQ,然后。。。。。
      1 /**************************************************************
      2     Problem: 5039
      3     User: Hammer_cwz_77
      4     Language: C++
      5     Result: Accepted
      6     Time:6100 ms
      7     Memory:10276 kb
      8 ****************************************************************/
      9  
     10 #include<cstdio>
     11 #include<cstring>
     12 #include<cstdlib>
     13 #include<algorithm>
     14 #include<cmath>
     15 using namespace std;
     16 typedef long long LL;
     17 LL mod;
     18 struct node
     19 {
     20     int l,r,lc,rc;
     21     LL c;
     22     LL mul,add;
     23     bool lazy;
     24     node(){lazy=false;}
     25 }tr[210000];int trlen;
     26 int n,m;int x[110000];
     27 void bt(int l,int r)
     28 {
     29     int now=++trlen;
     30     tr[now].l=l;tr[now].r=r;
     31     tr[now].lc=tr[now].rc=-1;tr[now].c=0;
     32     tr[now].mul=1;tr[now].add=0;
     33     if(l==r){tr[now].c=x[l]%mod;return ;}
     34     if(l<r)
     35     {
     36         int mid=(l+r)/2;
     37         tr[now].lc=trlen+1; bt(l,mid);
     38         tr[now].rc=trlen+1; bt(mid+1,r);
     39     }
     40     tr[now].c=tr[tr[now].lc].c+tr[tr[now].rc].c;
     41 }
     42 void lazy(int x)
     43 {
     44     int lc=tr[x].lc,rc=tr[x].rc;
     45     int l=tr[x].l,r=tr[x].r;int mid=(l+r)/2;
     46     if(lc!=-1)
     47     {
     48         tr[lc].c=(tr[lc].c*tr[x].mul)%mod;
     49         tr[lc].c=(tr[lc].c+tr[x].add*(mid-l+1))%mod;
     50         tr[lc].mul=(tr[lc].mul*tr[x].mul)%mod;
     51         tr[lc].add=(tr[lc].add*tr[x].mul)%mod;
     52         tr[lc].add=(tr[lc].add+tr[x].add)%mod;
     53     }
     54     if(rc!=-1)
     55     {
     56         tr[rc].c=(tr[rc].c*tr[x].mul)%mod;
     57         tr[rc].c=(tr[rc].c+tr[x].add*(r-mid))%mod;
     58         tr[rc].mul=(tr[rc].mul*tr[x].mul)%mod;
     59         tr[rc].add=(tr[rc].add*tr[x].mul)%mod;
     60         tr[rc].add=(tr[rc].add+tr[x].add)%mod;
     61     }
     62     tr[x].mul=1;tr[x].add=0;
     63 }
     64 void change_x(int now,int l,int r,LL c)//l~r +c
     65 {
     66     if(tr[now].l==l && tr[now].r==r)
     67     {
     68         tr[now].c=(tr[now].c+(r-l+1)*c)%mod;
     69         tr[now].add=(tr[now].add+c)%mod;
     70         return ;
     71     }
     72     int lc=tr[now].lc,rc=tr[now].rc;
     73     int mid=(tr[now].l+tr[now].r)/2;
     74     lazy(now);
     75     if(r<=mid)change_x(lc,l,r,c);
     76     else if(mid+1<=l)change_x(rc,l,r,c);
     77     else
     78     {
     79         change_x(lc,l,mid,c);
     80         change_x(rc,mid+1,r,c);
     81     }
     82     tr[now].c=(tr[lc].c+tr[rc].c)%mod;
     83 }
     84 void change_a(int now,int l,int r,LL c)//l~r *c
     85 {
     86     if(tr[now].l==l && tr[now].r==r)
     87     {
     88         tr[now].c=(tr[now].c*c)%mod;
     89         tr[now].mul=(tr[now].mul*c)%mod;
     90         tr[now].add=(tr[now].add*c)%mod;
     91         return ;
     92     }
     93     int lc=tr[now].lc,rc=tr[now].rc;
     94     int mid=(tr[now].l+tr[now].r)/2;
     95     lazy(now);
     96     if(r<=mid)change_a(lc,l,r,c);
     97     else if(mid+1<=l)change_a(rc,l,r,c);
     98     else
     99     {
    100         change_a(lc,l,mid,c);
    101         change_a(rc,mid+1,r,c);
    102     }
    103     tr[now].c=(tr[lc].c+tr[rc].c)%mod;
    104 }
    105 LL findsum(int now,int l,int r)
    106 {
    107     if(tr[now].l==l && tr[now].r==r)
    108     {
    109         lazy(now);
    110         return tr[now].c%mod;
    111     }
    112     int lc=tr[now].lc,rc=tr[now].rc;
    113     int mid=(tr[now].l+tr[now].r)/2;
    114     lazy(now);
    115     if(r<=mid)return findsum(lc,l,r);
    116     else if(mid+1<=l)return findsum(rc,l,r);
    117     else return ((findsum(lc,l,mid)%mod+findsum(rc,mid+1,r)%mod)%mod);
    118 }
    119 int main()
    120 {
    121     scanf("%d%lld",&n,&mod);
    122     for(int i=1;i<=n;i++)scanf("%d",&x[i]);
    123     trlen=0;bt(1,n);
    124     scanf("%d",&m);
    125     while(m--)
    126     {
    127         int q,t,g;LL c;
    128         scanf("%d%d%d",&q,&t,&g);
    129         if(q==3){printf("%lld
    ",findsum(1,t,g)%mod);continue;}
    130         scanf("%lld",&c);
    131         if(q==1)change_a(1,t,g,c);
    132         else change_x(1,t,g,c);
    133     }
    134     return 0;
    135 }

    ---恢复内容结束---

  • 相关阅读:
    c语言 12
    c语言中用结构体表示点的坐标,并计算两点之间的距离
    c语言 12
    c语言中结构体数组
    c语言 12-3
    c语言 12-2
    codevs3164 质因数分解
    codevs4438 YJQ Runs Upstairs
    codevs4439 YJQ Requires Food
    codevs4437 YJQ Arranges Sequences
  • 原文地址:https://www.cnblogs.com/Hammer-cwz-77/p/8545752.html
Copyright © 2011-2022 走看看