一、内容
题意: 有一个初始值为num = 1,给定2种操作,输入1 x代表 num = num * x,输入2 x代表 num 除以第x次的输入的x值。
二、思路
- 用线段树维护区间的乘积。每次操作的次数是线段树所在区间,当输入2 x时只需要把x位置的数修改为1就可以了。
三、代码
#include <cstdio>
#include <cstring>
typedef long long ll;
const int maxn = 1e5 + 5;
int t, q, M, code, num;
ll c[maxn << 2];
void build(int id, int l, int r) {
if (l == r) {
c[id] = 1;
return;
}
int mid = (l + r) >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
c[id] = c[id << 1] * c[id << 1 | 1];
}
void update(int id, int l, int r, int x, int v) {
if (l == r) {
c[id] = v;
return;
}
int mid = (l + r) >> 1;
if (x <= mid) {
update(id << 1, l, mid, x, v);
} else {
update(id << 1 | 1, mid + 1, r, x, v);
}
c[id] = (c[id << 1] * c[id << 1 | 1]) % M;
}
ll query(int id, int l, int r, int x, int y) {
if (x <= l && r <= y) {
return c[id];
}
ll ans = 1;
int mid = (l + r) >> 1;
if (x <= mid) {
ans = (ans * query(id << 1, l, mid, x, y)) % M;
}
if (y > mid) {
ans = (ans * query(id << 1 | 1, mid + 1, r, x, y)) % M;
}
return ans;
}
int main() {
scanf("%d", &t);
for (int i = 1; i <= t; i++) {
scanf("%d%d", &q, &M);
build(1, 1, q);
printf("Case #%d:\n", i);
for (int i = 1; i <= q; i++) {
scanf("%d%d", &code, &num);
if (code == 1) {
update(1, 1, q, i, num);
} else {
update(1, 1, q, num, 1);
}
printf("%d\n", c[1]);
}
}
return 0;
}