• 洛谷 P3373 【模板】线段树 2


    题目传送门

    本题相对于模板1多了乘法,但是代码里面加入了要考虑优先级的因素,所以并不是很好写.

    AC代码:

      1 #include<cstdio>
      2 #include<iostream>
      3 
      4 using namespace std;
      5 
      6 int n,m,p;
      7 long long a[100001];
      8 struct kkk {
      9     long long v,mul,add;
     10 }e[400005]; 
     11 
     12 inline void build(int bh,int l,int r) {
     13     e[bh].mul = 1;
     14     e[bh].add = 0;
     15     if(l == r) {
     16         e[bh].v = a[l] % p;
     17         return ;    
     18     }
     19     int mid = l + r >> 1;
     20     build(bh * 2,l,mid);
     21     build(bh * 2 + 1,mid + 1,r);
     22     e[bh].v = e[bh*2].v + e[bh*2+1].v;
     23     e[bh].v %= p;
     24     return ;
     25 }
     26 
     27 inline void pushdown(int bh,int l,int r) {
     28     int mid = (l + r) >> 1;
     29     e[bh*2].v = (e[bh*2].v * e[bh].mul + e[bh].add * (mid - l + 1)) % p;
     30     e[bh*2+1].v = (e[bh*2+1].v * e[bh].mul + e[bh].add * (r - mid)) % p;
     31     e[bh*2].mul = (e[bh*2].mul * e[bh].mul) % p;
     32     e[bh*2+1].mul = (e[bh*2+1].mul * e[bh].mul) % p;
     33     e[bh*2].add = (e[bh*2].add * e[bh].mul + e[bh].add) % p;
     34     e[bh*2+1].add = (e[bh*2+1].add * e[bh].mul + e[bh].add) % p;
     35     e[bh].mul = 1;
     36     e[bh].add = 0;
     37     return ;
     38 }
     39 
     40 inline void update_Multiply(int bh,int ll,int rr,int l,int r,long long _v) {
     41     if(r < ll || l > rr)
     42         return ;
     43     if(l <= ll && r >= rr) {
     44         e[bh].v = (e[bh].v * _v) % p;
     45         e[bh].mul = (e[bh].mul * _v) % p;
     46         e[bh].add = (e[bh].add * _v) % p;
     47         return ; 
     48     }    
     49     pushdown(bh,ll,rr);
     50     int mid = (ll + rr) >> 1;
     51     update_Multiply(bh * 2,ll,mid,l,r,_v);
     52     update_Multiply(bh * 2 + 1,mid + 1,rr,l,r,_v);
     53     e[bh].v = (e[bh*2].v + e[bh*2+1].v) % p;
     54     return ;
     55 }
     56 
     57 inline void update_Plus(int bh,int ll,int rr,int l,int r,long long _v) {
     58     if(r < ll || rr < l)
     59         return ;
     60     if(l <= ll && r >= rr) { 
     61         e[bh].add = (e[bh].add + _v) % p;
     62         e[bh].v = (e[bh].v + _v * (rr - ll + 1)) % p;
     63         return ;
     64     }
     65     pushdown(bh,ll,rr);
     66     int mid = (ll + rr) >> 1;
     67     update_Plus(bh * 2,ll,mid,l,r,_v);
     68     update_Plus(bh * 2 + 1,mid + 1,rr,l,r,_v);
     69     e[bh].v = (e[bh*2].v + e[bh*2+1].v) % p;
     70     return ;
     71 } 
     72 
     73 long long query(int bh,int ll,int rr,int l,int r) {
     74     if(r < ll || l > rr) 
     75         return 0;
     76     if(l <= ll && r >= rr)
     77         return e[bh].v;
     78     pushdown(bh,ll,rr);
     79     int mid = (ll + rr) >> 1;
     80     return (query(bh * 2,ll,mid,l,r) + query(bh * 2 + 1,mid + 1,rr,l,r)) % p;
     81 }
     82 
     83 int main()
     84 {
     85     scanf("%d%d%d",&n,&m,&p);
     86     for(int i = 1;i <= n; i++)
     87         scanf("%lld",&a[i]);
     88     build(1,1,n);
     89     while(m--) {
     90         int u,x,y;
     91         long long k;
     92         scanf("%d",&u);
     93         if(u == 1) {
     94             scanf("%d%d%lld",&x,&y,&k);
     95             update_Multiply(1,1,n,x,y,k);
     96         }
     97         if(u == 2) {
     98             scanf("%d%d%lld",&x,&y,&k);
     99             update_Plus(1,1,n,x,y,k);
    100         }
    101         if(u == 3) {
    102             scanf("%d%d",&x,&y);
    103             printf("%lld
    ",query(1,1,n,x,y) % p);
    104         }
    105     }
    106     return 0;
    107 }
    线段树乘法
  • 相关阅读:
    尾递归优化
    EOS Dawn 3.0 智能合约 -- 新格式
    以太坊钱包初探
    理解以太坊的椭圆曲线签名-校验签名
    以太坊交易字段
    以太坊的账户和交易
    以太坊源码探究之交易与签名
    以太坊交易签名
    L05 Laravel 教程
    thinkphp3.2配置redis缓存和文件缓存
  • 原文地址:https://www.cnblogs.com/lipeiyi520/p/11296301.html
Copyright © 2020-2023  润新知