zoukankan      html  css  js  c++  java
  • Luogu P3373 【模板】线段树 2

    题目描述

    如题,已知一个数列,你需要进行下面三种操作:

    1.将某区间每一个数乘上x

    2.将某区间每一个数加上x

    3.求出某区间每一个数的和

    输入输出格式

    输入格式:

    第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。

    第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

    接下来M行每行包含3或4个整数,表示一个操作,具体如下:

    操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k

    操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k

    操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果

    输出格式:

    输出包含若干行整数,即为所有操作3的结果。

    输入输出样例

    输入样例#1: 复制
    5 5 38
    1 5 4 2 3
    2 1 4 1
    3 2 5
    1 2 4 2
    2 3 5 5
    3 1 4
    输出样例#1: 复制
    17
    2

    说明

    时空限制:1000ms,128M

    数据规模:

    对于30%的数据:N<=8,M<=10

    对于70%的数据:N<=1000,M<=10000

    对于100%的数据:N<=100000,M<=100000

     1 //2018年2月22日21:51:08
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 int n, m, mo;
     9 int A[410000], B[410000], sum[410000], size[410000];
    10 
    11 void change(int k1){
    12     sum[k1] = (sum[k1*2]+sum[k1*2+1]) % mo;
    13 }
    14 
    15 void buildtree(int k1, int l, int r){
    16     size[k1] = r-l+1; B[k1] = 1;
    17     if(l == r){
    18         scanf("%d", &sum[k1]); return;
    19     }
    20     int mid = (l+r) >> 1;
    21     buildtree(k1*2, l, mid);
    22     buildtree(k1*2+1, mid+1, r);
    23     change(k1); 
    24 }
    25 
    26 void add(int k1, int x){
    27     A[k1] = (A[k1]+x) % mo;
    28     sum[k1] = (sum[k1]+1ll*size[k1]*x) % mo;
    29 }
    30 
    31 void chen(int k1, int x){
    32     A[k1] = 1ll*A[k1]*x % mo;
    33     B[k1] = 1ll*B[k1]*x % mo;
    34     sum[k1] = 1ll * sum[k1]*x % mo;
    35 }
    36 
    37 void pushdown(int k1){
    38     if(B[k1] != 1){
    39         chen(k1*2, B[k1]);
    40         chen(k1*2+1, B[k1]); B[k1] = 1; 
    41     }
    42     if(A[k1]){
    43         add(k1*2, A[k1]);
    44         add(k1*2+1, A[k1]);
    45         A[k1] = 0;
    46     }
    47 }
    48 
    49 void add(int k1, int l, int r, int L, int R, int x){
    50     if(l>R || r<L) return;
    51     if(l>=L && r<=R){
    52         add(k1, x);
    53         return;
    54     }
    55     int mid = (l+r) >> 1;
    56     pushdown(k1);
    57     add(k1*2, l, mid, L, R, x);
    58     add(k1*2+1, mid+1, r, L, R, x);
    59     change(k1);
    60 }
    61 
    62 void chen(int k1, int l, int r, int L, int R, int x){
    63     if(l>R || r<L) return;
    64     if(l>=L && r<=R){
    65         chen(k1, x); return;
    66     }
    67     int mid = l+r >> 1;
    68     pushdown(k1);
    69     chen(k1*2, l, mid, L, R, x);
    70     chen(k1*2+1, mid+1, r, L, R, x);
    71     change(k1);
    72 }
    73 
    74 int find(int k1, int l, int r, int L, int R){
    75     if(l>R || r<L) return 0;
    76     if(l>=L && r<=R) return sum[k1];
    77     int mid = l+r >> 1;
    78     pushdown(k1);
    79     return (find(k1*2,l,mid,L,R) + find(k1*2+1,mid+1,r,L,R) ) % mo;
    80 }
    81 
    82 int main(){
    83     scanf("%d%d%d", &n, &m, &mo);
    84     buildtree(1, 1, n);
    85     for(; m; m--){
    86         int k1, k2, k3;
    87         scanf("%d%d%d", &k1, &k2, &k3);
    88         if(k1 == 2){
    89             int k4; scanf("%d", &k4); add(1, 1, n, k2, k3, k4);
    90         }else if(k1 == 1){
    91             int k4; scanf("%d", &k4); chen(1, 1, n, k2, k3, k4);
    92         }else printf("%d
    ", find(1, 1, n, k2, k3));
    93     }
    94 
    95     return 0;
    96 }
  • 相关阅读:
    [Eclipse]GEF入门系列(四、其他功能)
    [Eclipse]GEF入门系列(三、应用实例)
    [Eclipse]GEF入门系列(一、Draw2D)
    打开Win2000的自动补齐功能
    让URLConnection使用代理服务器
    [Eclipse]GEF入门系列(序)
    给表格的单元格增加编辑功能(In place edit)
    设置Eclipse RCP程序的外观和首选项
    利用winrar自动备份重要资料(续,经验技巧)
    终于换了新电脑
  • 原文地址:https://www.cnblogs.com/sineagle/p/8460258.html
Copyright © 2011-2022 走看看