萌新刚学线段树,样例没过,疑似是乘法部分的问题但找不出
查看原帖
萌新刚学线段树,样例没过,疑似是乘法部分的问题但找不出
680446
artu_olara楼主2022/8/26 10:50
#include <bits/stdc++.h>
#define MAXN 100005
typedef long long ll;
using namespace std;

int p;
ll a[MAXN];
struct segtree {
  ll v, add, mul;
} st[4 * MAXN];

void init(int root, int l, int r) {
  st[root].add = 0;
  st[root].mul = 1;
  if (l == r)
    st[root].v = a[l];
  else {
    int mid = (l + r) >> 1;
    init(2 * root, l, mid);
    init(2 * root + 1, mid + 1, r);
    st[root].v = st[2 * root].v + st[2 * root + 1].v;
  }
  st[root].v %= p;
  return;
}

void Pushdown(int root, int l, int r){
  int mid = (l + r) >> 1;
  st[root * 2].v = (st[root * 2].v * st[root].mul + st[root].add * (mid - l + 1)) % p;
  st[root * 2 + 1].v = (st[root * 2 + 1].v * st[root].mul + st[root].add * (r - mid)) % p;

  st[root * 2].mul = (st[root * 2].mul * st[root].mul) % p;
  st[root * 2 + 1].mul = (st[root * 2 + 1].mul * st[root].mul) % p;
  st[root * 2].add = (st[root * 2].add * st[root].mul + st[root].add) % p;
  st[root * 2 + 1].add = (st[root * 2 + 1].add * st[root].mul + st[root].add) % p;

  st[root].mul = 1;
  st[root].add = 0;
  return ;
}

void multi(int root,int cl,int cr ,int l,int r,int k){
  if(r < cl || l > cr) return;
  if(l<=cl&&cr<=r){
    st[root].v=(st[root].v*k)%p;
    st[root].mul=(st[root].mul*k)%p;
    st[root].add=(st[root].add*k)%p;
    return;
  }
    Pushdown(root,cl,cr);
    int mid=(cl+cr)>>1;
    multi(2*root,cl,mid,l,r,k);
    multi(2*root+1,mid+1,cr,l,r,k);
    st[root].v=(st[2*root].v+st[2*root+1].v)%p;
    return ;
}


void addi(int root,int cl,int cr ,int l,int r,ll k){
  if(r < cl || l > cr) return;
  if(l<=cl&&cr<=r){
    st[root].v=(st[root].v+k*(cr-cl+1))%p;
    st[root].add=(st[root].add+k)%p;
    return;
  }
    Pushdown(root,cl,cr);
    int mid=(cl+cr)>>1;
    multi(2*root,cl,mid,l,r,k);
    multi(2*root+1,mid+1,cr,l,r,k);
    st[root].v=(st[2*root].v+st[2*root+1].v)%p;
    return ;
}

ll query(int root,int cl,int cr,int l,int r){
  if(r < cl || cr < l) return 0;
  if(l <= cl && cr <= r)
    return st[root].v;
  Pushdown(root,cl,cr);
  int mid=(cl+cr)>>1;
  return (query(root * 2,cl,mid,l,r) + query(root * 2 + 1,mid + 1,cr,l,r)) % p;
}

int main(){
  int n,m;
  scanf("%d%d%d",&n,&m,&p);
  for(int i=1; i<=n ;i++) scanf("%lld",&a[i]);
  init(1,1,n);
  while(m--){
    int opt,a,b;
    ll k;
    scanf("%d",&opt);
    if(opt==1){
      scanf("%d%d%lld",&a,&b,&k);
      multi(1,1,n,a,b,k);
    }else if(opt==2){
      scanf("%d%d%lld",&a,&b,&k);
      addi(1,1,n,a,b,k);
    }else{
      scanf("%d%d",&a,&b);
      printf("%lld\n",query(1,1,n,a,b));
    }
  }
  return 0;
}
2022/8/26 10:50
加载中...