• 洛谷3372线段树模板


    题目链接:https://www.luogu.com.cn/problem/P3372

    题目是经典的线段树模板题,要求支持三种操作:①、查询区间和取模的值 ②、给指定区间加上一个值  ③、给指定区间乘上一个值

    只要明确先做乘标记在做加标记就解决了问题,因为先做加标记再做乘标记的话就会出现加标记是小数的情况,不好计算,代码中我已明确如何下推标记等。有一点不足就是取模的耗费是非常巨大的,柯匡取模这么多次,我的用时大约是2300ms,是洛谷最优ac时间的三倍,模板写的还是很差劲的。

    代码如下:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef unsigned int ui;
      4 typedef long long ll;
      5 typedef unsigned long long ull;
      6 #define pf printf
      7 #define mem(a,b) memset(a,b,sizeof(a))
      8 #define prime1 1e9+7
      9 #define prime2 1e9+9
     10 #define pi 3.14159265
     11 #define lson l,mid,rt<<1
     12 #define rson mid+1,r,rt<<1|1
     13 #define scand(x) scanf("%llf",&x) 
     14 #define f(i,a,b) for(int i=a;i<=b;i++)
     15 #define scan(a) scanf("%d",&a)
     16 #define dbg(args) cout<<#args<<":"<<args<<endl;
     17 #define pb(i) push_back(i)
     18 #define ppb(x) pop_back(x)
     19 #define inf 0x3f3f3f3f
     20 #define maxn 100005
     21 int n,m;
     22 ll p;
     23 ll sum[maxn<<2],add[maxn<<2],mul[maxn<<2];
     24 //维护的区间形式上是 sum*mul+add 
     25 void pushup(int rt)
     26 {
     27     sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p;
     28 }
     29 void pushdown(int l,int r,int rt)
     30 {
     31     int mid=l+r>>1;
     32         mul[rt<<1]=(mul[rt<<1]*mul[rt])%p;//先推乘法标记,再推加法标记 
     33         mul[rt<<1|1]=(mul[rt<<1|1]*mul[rt])%p;
     34         sum[rt<<1]=(sum[rt<<1]*mul[rt]+add[rt]*(mid-l+1))%p;
     35         sum[rt<<1|1]=(sum[rt<<1|1]*mul[rt]+add[rt]*(r-mid))%p;
     36         add[rt<<1]=(add[rt<<1]*mul[rt]+add[rt])%p;
     37         add[rt<<1|1]=(add[rt<<1|1]*mul[rt]+add[rt])%p;
     38         mul[rt]=1;
     39         add[rt]=0;
     40  } 
     41 void build(int l,int r,int rt)
     42 {
     43     mul[rt]=1;//注意所有的区间段都要是mul=1,并不是只有最下层的点才有mul=1; 
     44     if(l==r)
     45     {
     46         scanf("%lld",&sum[rt]);
     47     //    mul[rt]=1;
     48         return ;
     49     }
     50     int mid=l+r>>1;
     51     build(lson);
     52     build(rson);
     53     pushup(rt);
     54 }
     55 ll query(int l,int r,int rt,int L,int R)
     56 {
     57     if(L<=l&&r<=R)
     58     {
     59         return sum[rt];
     60     }
     61     int mid=l+r>>1;
     62     ll ans=0;
     63     pushdown(l,r,rt);
     64     if(L<=mid)    ans=query(lson,L,R)%p;
     65     if(R>mid) ans=(ans+query(rson,L,R))%p;
     66     return ans;
     67 }
     68 void update_add(int l,int r,int rt,int L,int R,int C)
     69 {
     70     if(L<=l&&r<=R)
     71     {
     72         sum[rt]=(sum[rt]+C*(r-l+1))%p;
     73         add[rt]=(add[rt]+C)%p;
     74         return;
     75     }
     76     int mid=l+r>>1;
     77     pushdown(l,r,rt);//懒标记下推,否则下面区间的更新是错误的 
     78     if(L<=mid) update_add(lson,L,R,C);
     79     if(R>mid) update_add(rson,L,R,C);
     80     pushup(rt);
     81 }
     82 void update_mul(int l,int r,int rt,int L,int R,int C)
     83 {
     84     if(L<=l&&r<=R)  
     85     //区间值是 sum=a*mul+add,则*C之后mul<-mul*C,add<-add*C,sum<-sum*C;
     86     //即sum*C=a*mul*C+add*C 
     87     {
     88         sum[rt]=(sum[rt]*C)%p;
     89         add[rt]=(add[rt]*C)%p;
     90         mul[rt]=(mul[rt]*C)%p;
     91         return;
     92     }
     93     int mid=l+r>>1;
     94     pushdown(l,r,rt);
     95     if(L<=mid) update_mul(lson,L,R,C);
     96     if(R>mid) update_mul(rson,L,R,C);
     97     pushup(rt);
     98 }
     99 int main()
    100 {
    101     //freopen("input.txt","r",stdin);
    102     //freopen("output.txt","w",stdout);
    103     std::ios::sync_with_stdio(false);
    104     scan(n);
    105     scanf("%lld",&p);
    106     build(1,n,1);
    107     scan(m);
    108     int op,l,r,c;
    109     while(m--)
    110     {
    111         scan(op);
    112         if(op==1)
    113         {
    114             scanf("%d%d%d",&l,&r,&c);
    115             update_mul(1,n,1,l,r,c);
    116         }
    117         else if(op==2)
    118         {
    119             scanf("%d%d%d",&l,&r,&c);
    120             update_add(1,n,1,l,r,c);
    121         }
    122         else if(op==3)
    123         {
    124             scanf("%d%d",&l,&r);
    125             pf("%lld
    ",query(1,n,1,l,r));
    126         }
    127     }
    128  } 
  • 相关阅读:
    css的书写位置+元素分类
    选择器
    我的js运动库新
    js的相关距离
    关于小乌龟的使用
    linux 基础
    linux shell快捷操作【超级实用】
    算法面试常见问题【转】
    http://www.cnblogs.com/zhangchaoyang/archive/2012/08/28/2660929.html
    cocos2dx + vs安装使用
  • 原文地址:https://www.cnblogs.com/randy-lo/p/12444627.html
Copyright © 2020-2023  润新知