• [洛谷3373]【模板】线段树 2


    思路:

    线段树。同时维护两个 lazy tag ,一个维护乘,一个维护加。
    根据加法结合律,可以得出:当同一个结点进行两次加操作时,新的标记等于两次标记之和。
    根据乘法结合律,可以得出:当同一个结点进行两次乘操作时,新的标记等于两次标记之积。
    根据乘法分配律,可以得出:当同一个结点先进行了加操作,再进行乘操作时,两个标记都要乘以新乘上的值。

      1 #include<cstdio>
      2 #include<cctype>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<algorithm>
      6 using namespace std;
      7 #define ll long long
      8 #define maxn 100001
      9 #define root 1
     10 #define _left <<1
     11 #define _right <<1|1
     12 int n,m;
     13 ll mod;
     14 inline int getint() {
     15     char ch;
     16     while(!isdigit(ch=getchar()));
     17     int x=ch^'0';
     18     while(isdigit(ch=getchar())) x=((x+(x<<2))<<1)+(ch^'0');
     19     return x;
     20 }
     21 inline ll getll() {
     22     char ch;
     23     while(!isdigit(ch=getchar()));
     24     ll x=ch^'0';
     25     while(isdigit(ch=getchar())) x=((x+(x<<2))<<1)+(ch^'0');
     26     return x;
     27 }
     28 struct SegmentTree {
     29     ll val[maxn<<2],add[maxn<<2],mul[maxn<<2];
     30     void push_up(const int p) {
     31         val[p]=(val[p _left]+val[p _right])%mod;
     32     }
     33     void build(const int p,const int b,const int e) {
     34         mul[p]=1;
     35         add[p]=0;
     36         if(b==e) {
     37             val[p]=getll()%mod;
     38             return;
     39         }
     40         int mid=(b+e)>>1;
     41         build(p _left,b,mid);
     42         build(p _right,mid+1,e);
     43         push_up(p);
     44     }
     45     int length(const int b,const int e) {
     46         return e-b+1;
     47     }
     48     void push_down(const int p,const int b,const int e) {
     49         if(mul[p]!=1) {
     50             val[p _left]=val[p _left]*mul[p]%mod;
     51             val[p _right]=val[p _right]*mul[p]%mod;
     52             mul[p _left]=mul[p _left]*mul[p]%mod;
     53             mul[p _right]=mul[p _right]*mul[p]%mod;
     54             add[p _left]=add[p _left]*mul[p]%mod;
     55             add[p _right]=add[p _right]*mul[p]%mod;
     56             mul[p]=1; 
     57         }
     58         if(add[p]) {
     59             int mid=(b+e)>>1;
     60             val[p _left]=(val[p _left]+add[p]*length(b,mid))%mod;
     61             val[p _right]=(val[p _right]+add[p]*length(mid+1,e))%mod;
     62             add[p _left]=(add[p _left]+add[p])%mod;
     63             add[p _right]=(add[p _right]+add[p])%mod;
     64             add[p]=0;
     65         }
     66     }
     67     void modify_mul(const int p,const int b,const int e,const int l,const int r,const ll x) {
     68         if((b==l)&&(e==r)) {
     69             val[p]=val[p]*x%mod;
     70             mul[p]=mul[p]*x%mod;
     71             add[p]=add[p]*x%mod;
     72             return;
     73         }
     74         push_down(p,b,e);
     75         int mid=(b+e)>>1;
     76         if(l<=mid) modify_mul(p _left,b,mid,l,min(mid,r),x);
     77         if(r>mid) modify_mul(p _right,mid+1,e,max(mid+1,l),r,x);
     78         push_up(p);
     79     }
     80     void modify_add(const int p,const int b,const int e,const int l,const int r,const ll x) {
     81         if((b==l)&&(e==r)) {
     82             val[p]=(val[p]+x*length(b,e))%mod;
     83             add[p]=(add[p]+x)%mod;
     84             return;
     85         }
     86         push_down(p,b,e);
     87         int mid=(b+e)>>1;
     88         if(l<=mid) modify_add(p _left,b,mid,l,min(mid,r),x);
     89         if(r>mid) modify_add(p _right,mid+1,e,max(mid+1,l),r,x);
     90         push_up(p);
     91     }
     92     ll query(const int p,const int b,const int e,const int l,const int r) {
     93         if((b==l)&&(e==r)) {
     94             return val[p];
     95         }
     96         int mid=(b+e)>>1;
     97         ll ans=0;
     98         push_down(p,b,e);
     99         if(l<=mid) ans=(ans+query(p _left,b,mid,l,min(mid,r)))%mod;
    100         if(r>mid) ans=(ans+query(p _right,mid+1,e,max(mid+1,l),r))%mod;
    101         return ans;
    102     }
    103 };
    104 SegmentTree tree;
    105 int main() {
    106     n=getint();
    107     m=getint();
    108     mod=getll();
    109     tree.build(root,1,n);
    110     while(m--) {
    111         int op=getint(),x=getint(),y=getint();
    112         if(op==1) {
    113             ll k=getll()%mod;
    114             tree.modify_mul(root,1,n,x,y,k);
    115             continue;
    116         }
    117         if(op==2) {
    118             ll k=getll()%mod;
    119             tree.modify_add(root,1,n,x,y,k);
    120             continue;
    121         }
    122         printf("%lld
    ",tree.query(root,1,n,x,y));
    123     }
    124     return 0;
    125 }
  • 相关阅读:
    判断大小写数字个数,取交集和并集
    软件工程总结
    正则表达式(邮箱)
    今天距离你生日的天数
    字符数量,查回文
    解决一个表单中的两个或者多个按钮提交到不同的页面中问题
    jsp前台输入框不输入值,后台怎么取出整型?
    第十次作业
    CMD命令行
    Kali渗透安卓手机
  • 原文地址:https://www.cnblogs.com/skylee03/p/6875443.html
Copyright © 2020-2023  润新知