zoukankan      html  css  js  c++  java
  • 线段树 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的结果。
    输入输出样例
    输入样例#15 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
    输出样例#117
    2
    
    时空限制:1000ms,128M
    数据规模:
    对于30%的数据:N<=8,M<=10
    对于70%的数据:N<=1000,M<=10000
    对于100%的数据:N<=100000,M<=100000
    (数据已经过加强^_^)
    题面
     1 #include<iostream>
     2 #include<cstdio>
     3 #define ll long long
     4 using namespace std;
     5 const ll N=100002;
     6 ll n,mod,a[N],add[N*10],mul[N*10],sum[N*10];
     7 ll m,op,x,y,k;
     8 void build(ll o,ll l,ll r)
     9 {
    10     mul[o]=1;add[o]=0;
    11     if(l==r)
    12     {
    13         sum[o]=a[l]%mod;
    14         return;
    15     }
    16     ll mid=(l+r)>>1;
    17     build(o<<1,l,mid);build(o<<1|1,mid+1,r);
    18     sum[o]=(sum[o<<1]+sum[o<<1|1])%mod;
    19 }
    20 void down(ll o,ll l,ll r,ll mid)
    21 {
    22     if(add[o]==0 && mul[o]==1) return;
    23     add[o<<1]=(add[o<<1]*mul[o]+add[o])%mod;
    24     mul[o<<1]=mul[o<<1]*mul[o]%mod;
    25     sum[o<<1]=(sum[o<<1]*mul[o]%mod+add[o]*(mid-l+1)%mod)%mod;
    26     
    27     add[o<<1|1]=(add[o<<1|1]*mul[o]+add[o])%mod;
    28     mul[o<<1|1]=mul[o<<1|1]*mul[o]%mod;
    29     sum[o<<1|1]=(sum[o<<1|1]*mul[o]+add[o]*(r-(mid+1)+1))%mod;
    30     
    31     add[o]=0;mul[o]=1;
    32 }
    33 void Mul(ll o,ll l,ll r,ll x,ll y,ll k)
    34 {
    35     if(x<=l && y>=r)
    36     {
    37         add[o]=add[o]%mod*k%mod;
    38         sum[o]=sum[o]*k%mod%mod;
    39         mul[o]=mul[o]*k%mod;
    40         return;
    41     }
    42     ll mid=(l+r)>>1;
    43     down(o,l,r,mid);
    44     if(x<=mid) Mul(o<<1,l,mid,x,y,k);
    45     if(y>=mid+1) Mul(o<<1|1,mid+1,r,x,y,k);
    46     sum[o]=(sum[o<<1]+sum[o<<1|1])%mod;
    47 }
    48 void Add(ll o,ll l,ll r,ll x,ll y,ll k)
    49 {
    50     if(x<=l && y>=r)
    51     {
    52         add[o]=(add[o]+k)%mod;
    53         sum[o]=(sum[o]+k*(r-l+1)%mod)%mod;
    54         return;
    55     }
    56     ll mid=(l+r)>>1;
    57     down(o,l,r,mid);
    58     if(x<=mid) Add(o<<1,l,mid,x,y,k);
    59     if(y>=mid+1) Add(o<<1|1,mid+1,r,x,y,k);
    60     sum[o]=(sum[o<<1]+sum[o<<1|1])%mod;
    61 }
    62 ll query(ll o,ll l,ll r,ll x,ll y)
    63 {
    64     if(x<=l && y>=r) 
    65     {
    66         return sum[o];
    67     }
    68     ll tot=0,mid=(l+r)>>1;
    69     down(o,l,r,mid);
    70     if(x<=mid) tot=(tot+query(o<<1,l,mid,x,y))%mod;
    71     if(y>=mid+1) tot=(tot+query(o<<1|1,mid+1,r,x,y))%mod;
    72     return tot;
    73 }
    74 int main()
    75 {
    76     scanf("%lld%lld%lld",&n,&m,&mod);
    77     for(ll i=1;i<=n;++i) scanf("%lld",&a[i]);
    78     build(1,1,n);
    79     while(m--)
    80     {
    81         scanf("%lld%lld%lld",&op,&x,&y);
    82         if(op==1) 
    83         {
    84             scanf("%lld",&k);
    85             Mul(1,1,n,x,y,k);
    86         }
    87         if(op==2)
    88         {
    89             scanf("%lld",&k);
    90             Add(1,1,n,x,y,k);
    91         }
    92         if(op==3) 
    93          printf("%lld
    ",query(1,1,n,x,y)%mod);
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    二分法
    php冒泡排序
    php位运算
    php学习函数如何执行的
    php学习 打星星
    小程序的学习备注
    一个IP与多个域名绑定
    apache、mysql、php核心、phpmyadmin的安装及相互关联
    php虚拟主机配置( 输入网址 对应 ip地址)
    ORA-01084: OCI 调用中的参数无效
  • 原文地址:https://www.cnblogs.com/adelalove/p/8683929.html
Copyright © 2011-2022 走看看