• bzoj1798--维护序列--线段树


    Description

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

    Input

    第一行两个整数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)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

    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

    HINT

    【样例说明】

    初始时数列为(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。


    测试数据规模如下表所示
    数据编号 1 2 3 4 5 6 7 8 9 10
    N= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000
    M= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000

    题解:

      码来当板子咯qwq

      需要注意的是在维护add和mul两个lazy标记时,它们的优先级总为mul先于add标记。

      在区间乘的时候,add标记和区间val也要跟着乘,在下传标记时mul的优先级也总是高于add标记。

      1 #include<cmath>
      2 #include<algorithm>
      3 #include<cstdio>
      4 #include<iostream>
      5 #include<cstring>
      6 #define ll long long
      7 using namespace std;
      8 const int maxn=100009;
      9 int n,m,mod,a[maxn];
     10 struct tree
     11 {
     12     int l,r;
     13     ll val,add,mul;
     14 }tr[maxn<<2];
     15 
     16 void build(int x,int la,int ra)
     17 {
     18     tr[x].l=la;tr[x].r=ra;
     19     tr[x].add=0;tr[x].mul=1;//加和乘的性质,add为0,mul为1
     20     if(la==ra)
     21     {
     22         tr[x].val=a[la]%mod;
     23         return;
     24     }
     25     int mid=(la+ra)>>1;
     26     build(x<<1,la,mid);build(x<<1|1,mid+1,ra);
     27     tr[x].val=(tr[x<<1].val+tr[x<<1|1].val)%mod;
     28     return;
     29 }
     30 
     31 void down(int x)
     32 {
     33     if(tr[x].mul==1&&tr[x].add==0)return;
     34 
     35     tr[x<<1].mul=(tr[x<<1].mul*tr[x].mul)%mod;
     36     tr[x<<1|1].mul=(tr[x<<1|1].mul*tr[x].mul)%mod;
     37     
     38     tr[x<<1].add=(tr[x<<1].add*tr[x].mul+tr[x].add)%mod;
     39     tr[x<<1|1].add=(tr[x<<1|1].add*tr[x].mul+tr[x].add)%mod;
     40     
     41     tr[x<<1].val=(tr[x<<1].val*tr[x].mul + tr[x].add*(tr[x<<1].r-tr[x<<1].l+1))%mod;
     42     tr[x<<1|1].val=(tr[x<<1|1].val*tr[x].mul + tr[x].add*(tr[x<<1|1].r-tr[x<<1|1].l+1))%mod;
     43     
     44     tr[x].add=0;tr[x].mul=1;
     45 }
     46 
     47 void multiply(int x,int la,int ra,int num)
     48 {
     49     if(tr[x].l>ra||tr[x].r<la)return;
     50 
     51     if(la<=tr[x].l&&tr[x].r<=ra)
     52     {
     53         tr[x].mul=(tr[x].mul*num)%mod;
     54         tr[x].add=(tr[x].add*num)%mod;
     55         tr[x].val=(tr[x].val*num)%mod;
     56         return;
     57     }
     58     if(tr[x].l==tr[x].r)return;
     59     down(x);
     60     multiply(x<<1,la,ra,num);
     61     multiply(x<<1|1,la,ra,num);
     62     tr[x].val=(tr[x<<1].val+tr[x<<1|1].val)%mod;
     63 }
     64 
     65 void add(int x,int la,int ra,int num)
     66 {
     67     if(tr[x].l>ra||tr[x].r<la)return;
     68 
     69     if(la<=tr[x].l&&tr[x].r<=ra)
     70     {
     71         tr[x].add=(tr[x].add+num)%mod;
     72         tr[x].val=(tr[x].val+(tr[x].r-tr[x].l+1)*num)%mod;
     73         return;
     74     }
     75     if(tr[x].l==tr[x].r)return;
     76     
     77     down(x);
     78     add(x<<1,la,ra,num);
     79     add(x<<1|1,la,ra,num);
     80     tr[x].val=(tr[x<<1].val+tr[x<<1|1].val)%mod;
     81     return;
     82 }
     83 
     84 ll ask(int x,int la,int ra)
     85 {
     86     if(tr[x].l>ra||tr[x].r<la)return 0;
     87     
     88     if(la<=tr[x].l&&tr[x].r<=ra)
     89         return tr[x].val%mod;
     90 
     91     if(tr[x].l==tr[x].r)return 0;
     92     
     93     down(x);
     94     return (ask(x<<1,la,ra)+ask(x<<1|1,la,ra))%mod;
     95 }
     96 
     97 int main()
     98 {
     99     scanf("%d%d",&n,&mod);
    100     for(int i=1;i<=n;i++)
    101         scanf("%d",&a[i]);
    102     build(1,1,n);
    103     scanf("%d",&m);
    104     while(m--)
    105     {
    106         int op;
    107         scanf("%d",&op);
    108         if(op==1)
    109         {
    110             int t,g,c;
    111             scanf("%d%d%d",&t,&g,&c);
    112             multiply(1,t,g,c);
    113         }
    114         else if(op==2)
    115         {
    116             int t,g,c;
    117             scanf("%d%d%d",&t,&g,&c);
    118             add(1,t,g,c);
    119         }
    120         else if(op==3)
    121         {
    122             int t,g;
    123             scanf("%d%d",&t,&g);
    124             printf("%lld
    ",ask(1,t,g)%mod);
    125         }
    126     }
    127     return 0;
    128 }
    View Code
  • 相关阅读:
    C++成员函数在内存中的存储方式
    C++重写(覆盖)、重载、重定义、
    C++中的覆盖与隐藏(详细讲解)
    c++中被忽视的隐藏
    C++对象的内存分布和虚函数表
    C++ explicit关键字详解
    命名空间 extern的用法 static全局变量
    extern和include的作用
    extern用法总结
    KMP算法
  • 原文地址:https://www.cnblogs.com/Beckinsale/p/7586068.html
Copyright © 2020-2023  润新知