P3373 【模板】线段树 2

简介: 笔记

题目描述


如题,已知一个数列,你需要进行下面三种操作:


将某区间每一个数乘上 x


将某区间每一个数加上 x

求出某区间每一个数的和


输入格式

第一行包含三个整数 n , m , p 分别表示该数列数字的个数、操作的总个数和模数。


第二行包含 n 个用空格分隔的整数,其中第 i  个数字表示数列第 i项的初始值。


接下来 m 行每行包含若干个整数,表示一个操作,具体如下:


操作 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


代码


结构体

#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
typedef long long LL;
#define ls u<<1
#define rs u<<1|1
struct node {
  int l, r;
  int add, mul, sum;
} tr[N << 2];
int n, m, mod;
int a[N];
// *x  +y
int calc(int u, int x, int y) {
  tr[u].sum = ((LL)tr[u].sum * x + (LL)(tr[u].r - tr[u].l + 1) * y) % mod;
  tr[u].add = ((LL)tr[u].add * x + y) % mod;
  tr[u].mul = ((LL)tr[u].mul * x) % mod;
}
void pushup(int u) {
  tr[u].sum = ((LL)tr[ls].sum + tr[rs].sum) % mod;
}
void pushdown(int u) {
  int x = tr[u].mul, y = tr[u].add;
  calc(ls, x, y), calc(rs, x, y);
  tr[u].add = 0, tr[u].mul = 1;
}
void build(int u, int l, int r) {
  tr[u] = {l, r, 0, 1};
  if(l == r) { tr[u].sum = a[l]; return ;}
  int mid = l + r >> 1;
  build(ls, l, mid), build(rs, mid + 1, r);
  pushup(u);
}
void modify(int u, int l, int r, int x, int y) {
  if(tr[u].l >= l && tr[u].r <= r) {
    calc(u, x, y);
    return ;
  }
  pushdown(u);
  int mid = tr[u].l + tr[u].r >> 1;
  if(l <= mid) modify(ls, l, r, x, y);
  if(r > mid) modify(rs, l, r, x, y);
  pushup(u);
}
int query(int u, int l, int r) {
  if(tr[u].l >= l && tr[u].r <= r) return tr[u].sum;
  pushdown(u);
  int mid = tr[u].l + tr[u].r >> 1;
  int v = 0;
  if(l <= mid) v = query(ls, l, r);
  if(r > mid) v = ((LL)v + query(rs, l, r)) % mod;
  return v % mod;
}
int main() {
  cin >> n >> m >> mod;
  for (int i = 1; i <= n; i++) cin >> a[i];
  build(1, 1, n);
  // cin >> m;
  int op, x, y, k;
  while(m--) {
    cin >> op >> x >> y;
    if(op == 1) {
      cin >> k;
      modify(1, x, y, k, 0);
    } else if(op == 2) {
      cin >> k;
      modify(1, x, y, 1, k);
    } else if(op == 3) {
      cout << query(1, x, y) << endl;
    }
  }
  return 0;
}
  • 数组
#include<bits/stdc++.h>
using namespace std;
#define ls u<<1
#define rs u<<1|1
#define LL long long
const int N = 1000010;
int n, m, Mod, a[N], L[N << 2], R[N << 2], tr[N << 2], add[N << 2], mul[N << 2];
void pushup(int u) {
  tr[u] = (tr[ls] + tr[rs]) % Mod;
}
// +p *q
void calc(int u, int p, int q) {
  tr[u] = ((LL)tr[u] * q + (LL)(R[u] - L[u] + 1) * p) % Mod;
  add[u] = ((LL)add[u] * q + p) % Mod;
  mul[u] = (LL)mul[u] * q % Mod;
}
void pushdown(int u) {
  int p = add[u], q = mul[u];
  calc(ls, p, q), calc(rs, p, q);
  add[u] = 0, mul[u] = 1;
}
void build(int u, int l, int r) {
  L[u] = l, R[u] = r;
  if(l == r) {
    tr[u] = a[l];
    add[u] = 0, mul[u] = 1;
    return ;
  }
  int mid = l + r >> 1;
  build(ls, l, mid), build(rs, mid + 1, r);
  add[u] = 0, mul[u] = 1;
  pushup(u);
}
// +p *q
void modify(int u, int l, int r, int p, int q) {
  int ll = L[u], rr = R[u];
  if(ll >= l && rr <= r) {
    calc(u, p, q);
    return ;
  }
  pushdown(u);
  int mid = ll + rr >> 1;
  if(l <= mid) modify(ls, l, r, p, q);
  if(r > mid) modify(rs, l, r, p, q);
  pushup(u);
}
int query(int u, int l, int r) {
  int ll = L[u], rr = R[u];
  if(ll >= l && rr <= r) {
    return tr[u];
  }
  pushdown(u);
  int mid = ll + rr >> 1;
  int ans = 0;
  if(l <= mid) ans = query(ls, l, r);
  if(r > mid) ans = ((LL)ans + query(rs, l, r)) % Mod;
  return ans;
}
int main() {
  scanf("%d%d%d", &n, &m, &Mod);
  for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
  build(1, 1, n);
  int op, x, y, k;
  while(m--) {
    scanf("%d%d%d", &op, &x, &y);
    if(op == 1) {
      scanf("%d", &k);
      modify(1, x, y, 0, k);
    } else if(op == 2) {
      scanf("%d", &k);
      modify(1, x, y, k, 1);
    } else {
      printf("%d\n", query(1, x, y));
    }
  }
  return 0;
}
相关文章
|
1月前
树状数组模板
树状数组模板
23 0
|
1月前
|
Python
{二分模板}
{二分模板}
9 0
|
1月前
线段树模板
线段树模板
30 0
|
9月前
|
机器学习/深度学习
P1873 砍树(二分查找模板)
P1873 砍树(二分查找模板)
79 0
|
10月前
|
SQL 人工智能 开发框架
线段树模板+例题
线段树模板+例题
56 1
二分搜索的三种模板
二分搜索的三种模板
50 0
|
存储 算法
线段树模板与练习
线段树模板与练习
81 0