• 线段树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的结果。

    输入输出样例

    输入样例#1: 复制
    5 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
    输出样例#1: 复制
    17
    2

    说明

    时空限制:1000ms,128M

    数据规模:

    对于30%的数据:N<=8,M<=10

    对于70%的数据:N<=1000,M<=10000

    对于100%的数据:N<=100000,M<=100000

    (数据已经过加强^_^)

    样例说明:

    故输出应为17、2(40 mod 38=2)


    就是基本的线段树操作,但是有几个地方要多注意下,也就是我犯错的地方。

    1 乘法优先级高于加法

    2 初始tag数组时不能用memset把mul全变成1,要在build中赋初始值

    3 long long记得最后要改好

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    
    #define ll long long
    #define il inline
    #define db double
    
    using namespace std;
    
    il int gi()
    {
      int x=0,y=1;
      char ch=getchar();
      while(ch<'0'||ch>'9')
        {
          if(ch=='-')
    	y=-1;
          ch=getchar();
        }
      while(ch>='0'&&ch<='9')
        {
          x=x*10+ch-'0';
          ch=getchar();
        }
      return x*y;
    }
    
    il ll gl()
    {
      ll x=0,y=1;
      char ch=getchar();
      while(ch<'0'||ch>'9')
        {
          if(ch=='-')
    	y=-1;
          ch=getchar();
        }
      while(ch>='0'&&ch<='9')
        {
          x=x*10+ch-'0';
          ch=getchar();
        }
      return x*y;
    }
    
    int n,mm;
    ll p;
    ll a[100045],sum[400045];
    ll add[400045],mul[400045];
    
    il void build(int rt,int l,int r)
    {
      mul[rt]=1;
      add[rt]=0;
      int m=(l+r)>>1;
      if(l==r)
        {
          sum[rt]=a[l];
          return;
        }
      build(rt<<1,l,m);
      build(rt<<1|1,m+1,r);
      sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p;
    } 
    
    il void pushdown(int rt,int l,int r)
    {
      int m=(l+r)>>1;
      sum[rt<<1]=(sum[rt<<1]*mul[rt]%p+add[rt]*(m-l+1)%p)%p;
      sum[rt<<1|1]=(sum[rt<<1|1]*mul[rt]%p+add[rt]*(r-m)%p)%p;
      mul[rt<<1]=mul[rt<<1]*mul[rt]%p;
      mul[rt<<1|1]=mul[rt<<1|1]*mul[rt]%p;
      add[rt<<1]=(add[rt<<1]*mul[rt]%p+add[rt])%p;
      add[rt<<1|1]=(add[rt<<1|1]*mul[rt]%p+add[rt])%p;
      mul[rt]=1;
      add[rt]=0;
    }
    
    il void update1(int rt,int l,int r,int L,int R,ll k)
    {
      if(L<=l&&R>=r)
        {
          sum[rt]=sum[rt]*k%p;
          mul[rt]=mul[rt]*k%p;
          add[rt]=add[rt]*k%p;
          return;
        }
      pushdown(rt,l,r);
      int m=(l+r)>>1;
      if(L<=m)
        update1(rt<<1,l,m,L,R,k);
      if(R>m)
        update1(rt<<1|1,m+1,r,L,R,k);
      sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p;
    }
    
    il void update2(int rt,int l,int r,int L,int R,ll k)
    {
      if(L<=l&&R>=r)
        {
          sum[rt]=(sum[rt]+k*(r-l+1))%p;
          add[rt]=(k+add[rt])%p;
          return;
        }
      pushdown(rt,l,r);
      int m=(l+r)>>1;
      if(L<=m)
        update2(rt<<1,l,m,L,R,k);
      if(R>m)
        update2(rt<<1|1,m+1,r,L,R,k);
      sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p;
    }
    
    il ll query(int rt,int l,int r,int L,int R)
    {
      if(L<=l&&R>=r)
        return sum[rt];
      pushdown(rt,l,r);
      int m=(l+r)>>1;
      ll s=0;
      if(L<=m)
        s=(s+query(rt<<1,l,m,L,R))%p;
      if(R>m)
        s=(s+query(rt<<1|1,m+1,r,L,R))%p;
      return s%p;
    }
    
    int main()
    {
      n=gi(),mm=gi(),p=gl();
      for(int i=1;i<=n;i++)
        a[i]=gl();
      build(1,1,n);
      int x,y,k,r;
      for(int i=1;i<=mm;i++)
        {
          r=gi();
          if(r==1)
    	{
    	  x=gi(),y=gi(),k=gl();
    	  update1(1,1,n,x,y,k);
    	}
          if(r==2)
    	{
    	  x=gi(),y=gi(),k=gl();
    	  update2(1,1,n,x,y,k);
    	}
          if(r==3)
    	{
    	  x=gi(),y=gi();
    	  printf("%lld
    ",query(1,1,n,x,y));
    	}
        }
      return 0;
    }
    
  • 相关阅读:
    Typora的使用
    selenium中webdriver提供的八大定位元素方法
    JAVA的Data和Timestamp的相互转换
    Jmeter设置参数作为断言依据
    Springboot +Poi 导入Excel表格
    window.location.reload();
    带参数的链接跳转
    Layui结束时间不能小于开始时间
    后台返回数据渲染Layui表格
    Layui中layedit模板的使用
  • 原文地址:https://www.cnblogs.com/gshdyjz/p/9819012.html
Copyright © 2020-2023  润新知