zoukankan      html  css  js  c++  java
  • 【模板】线段树区间加、区间乘、区间和、区间平方和

      1 #include<bits/stdc++.h>
      2 #define LL long long
      3 #define L(x) x<<1    //左儿子 x*2
      4 #define R(x) x<<1|1 //右儿子  x*2+1
      5 const int maxn =1e5+5;
      6 using namespace std;
      7 LL n,m,num[maxn];
      8 LL mod;                     //膜数
      9 inline LL read() {
     10     LL x=0,f=1;
     11     char ch=getchar();
     12     while(ch<'0'||ch>'9') f=(ch=='-')?-1:1,ch=getchar();
     13     while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
     14     return x*f;
     15 }
     16 struct T {
     17     LL l,r;
     18     LL sum,add,mul;
     19 } tree[maxn<<2];//注意开long long 和四倍空间
     20 inline void update(LL p) {
     21     tree[p].sum=(tree[L(p)].sum+tree[R(p)].sum)%mod;
     22     return;
     23 }
     24 inline void spread(LL p) {
     25     LL mid=(tree[p].l+tree[p].r)>>1;
     26     if(tree[p].mul!=1) {
     27         tree[L(p)].mul=(tree[L(p)].mul*tree[p].mul)%mod;
     28         tree[R(p)].mul=(tree[R(p)].mul*tree[p].mul)%mod;
     29         tree[L(p)].add=(tree[L(p)].add*tree[p].mul)%mod;
     30         tree[R(p)].add=(tree[R(p)].add*tree[p].mul)%mod;
     31         tree[L(p)].sum=(tree[L(p)].sum*tree[p].mul)%mod;
     32         tree[R(p)].sum=(tree[R(p)].sum*tree[p].mul)%mod;
     33         tree[p].mul=1;
     34     }
     35     if(tree[p].add) {
     36         tree[L(p)].add=(tree[L(p)].add+tree[p].add)%mod;
     37         tree[R(p)].add=(tree[R(p)].add+tree[p].add)%mod;
     38         tree[L(p)].sum=(tree[L(p)].sum+tree[p].add*(mid-tree[p].l+1))%mod;
     39         tree[R(p)].sum=(tree[R(p)].sum+tree[p].add*(tree[p].r-mid))%mod;//tree[p].r-mid不加1
     40         tree[p].add=0;
     41     }
     42     return;
     43 }
     44 inline void build(LL l,LL r,LL p) {//建树
     45     tree[p].l=l,tree[p].r=r,tree[p].mul=1;
     46     if(l==r) {
     47         tree[p].sum=num[l];
     48         tree[p].mul=1;
     49         return;
     50     }
     51     LL mid=(tree[p].l+tree[p].r)>>1;
     52     build(l,mid,L(p));
     53     build(mid+1,r,R(p));
     54     update(p);
     55     return;
     56 }
     57 inline void change1(LL l,LL r,LL p,LL v) {//区间增值
     58     if(tree[p].l==l&&tree[p].r==r) {
     59         tree[p].add=(tree[p].add+v)%mod;
     60         tree[p].sum=(tree[p].sum+v*(r-l+1))%mod;
     61         return;
     62     }
     63     spread(p);
     64     LL mid=(tree[p].l+tree[p].r)>>1;
     65     if(r<=mid) change1(l,r,L(p),v);
     66     else if(l>mid) change1(l,r,R(p),v);
     67     else change1(l,mid,L(p),v),change1(mid+1,r,R(p),v);
     68     update(p);
     69     return;
     70 }
     71 inline void change2(LL l,LL r,LL p,LL v) {//区间乘法
     72 
     73     if(tree[p].l==l&&tree[p].r==r) {
     74         tree[p].mul=(tree[p].mul*v)%mod;
     75         tree[p].sum=(tree[p].sum*v)%mod;
     76         tree[p].add=(tree[p].add*v)%mod;
     77         return;
     78     }
     79     spread(p);
     80     LL mid=(tree[p].l+tree[p].r)>>1;
     81     if(r<=mid) change2(l,r,L(p),v);
     82     else if(l>mid) change2(l,r,R(p),v);
     83     else change2(l,mid,L(p),v),change2(mid+1,r,R(p),v);
     84     update(p);
     85     return;
     86 }
     87 inline LL ask_sum1(LL l,LL r,LL p) {//区间和
     88     if(tree[p].l==l&&tree[p].r==r) {
     89         return tree[p].sum%mod;
     90     }
     91     spread(p);
     92     LL mid=(tree[p].l+tree[p].r)>>1;
     93     if(r<=mid) return ask_sum1(l,r,L(p))%mod;
     94     else if(l>mid) return ask_sum1(l,r,R(p))%mod;
     95     else  return (ask_sum1(l,mid,L(p))%mod+ask_sum1(mid+1,r,R(p))%mod)%mod;
     96 }
     97 
     98 inline LL ask_sum2(LL l,LL r,LL p) {//区间平方和
     99     if(tree[p].l==tree[p].r) {
    100         return tree[p].sum*tree[p].sum;
    101     }
    102     spread(p);
    103     LL mid=(tree[p].l+tree[p].r)>>1;
    104     if(r<=mid) return ask_sum2(l,r,L(p));
    105     else if(l>mid) return ask_sum2(l,r,R(p));
    106     else  return ask_sum2(l,mid,L(p))+ask_sum2(mid+1,r,R(p));
    107 }
    108 
    109 LL opt,l,r,v;
    110 int main() {
    111     n=read(),m=read();
    112     mod=read();
    113     for(int i=1; i<=n; i++) num[i]=read();
    114     build(1,n,1);
    115     while(m--) {
    116         opt=read();
    117         if(opt==3) {    
    118             l=read(),r=read();
    119             printf("%lld
    ",ask_sum1(l,r,1)%mod);//询问区间和
    120         }
    121         if(opt==4) {
    122             l=read(),r=read();
    123             printf("%lld
    ",ask_sum2(l,r,1)%mod);//询问区间平方和
    124         }
    125         if(opt==1) {
    126             l=read(),r=read(),v=read();
    127             change2(l,r,1,v);//区间乘
    128         }
    129         if(opt==2) {
    130             l=read(),r=read(),v=read();
    131             change1(l,r,1,v);//区间加
    132         }
    133     }
    134     return 0;
    135 }
  • 相关阅读:
    node.js学习二---------------------同步API和异步API的区别
    node.js学习一---------------------模块的导入
    ES6函数的特性(箭头语法)
    10分钟了解Android的Handler机制
    10分钟了解Android的事件分发
    SwipeRefreshLayout,用最少的代码定制最美的上下拉刷新样式
    手把手教你React Native 实战之开山篇《一》
    Android 组件化方案探索与思考
    2018谷歌I/O开发者大会8大看点汇总 新品有哪些
    Glide高级详解—缓存与解码复用
  • 原文地址:https://www.cnblogs.com/Whiteying/p/10056288.html
Copyright © 2011-2022 走看看