解题报告
发现这个过程用操作序列描述起来比较清晰
比如一溜乘法操作
1 2
1 2
1 4
1 6
2 3
前四个操作就可以描述成
x = 1
| *2
x = 2
| *4
x = 8
| *6
x = 48
而除法操作就是把对应操作序号删掉,换句话说,把乘数改成 1
x = 1
| *2
x = 2
| *1
x = 2
| *6
x = 12
接下来把操作序列横着画
1 1 1 1 1 1 1 ... x = 1
2 4 6 1 1 1 1 ... x = 2 * 4 * 6 = 48
2 1 6 1 1 1 1 ... x = 2 * 1 * 6 = 12
发现这不就是个前缀积吗!
于是题目转化成了:
给定一个全为 1 的序列,每次修改一个数,求前缀积。
线段树一波搞定。
代码实现
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#define forall(G,i) for (int i = 0, __for_siz__ = (int) (G).size(); i < __for_siz__; ++i)
#define DEBUG(x) std::cerr << #x << " = " << x << std::endl;
#define ALL(x) (x).begin(), (x).end()
#define MP std::make_pair
#define se second
#define fi first
using std::cin;
using std::cout;
using std::endl;
inline int read() {
int s = 0, x = 1; char ch = getchar();
while (!isdigit(ch)) { if (ch == '-') x = -x; ch = getchar(); }
while (isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); }
return s * x;
}
int Q, M;
struct SegmentTree {
static const int MAXQ = 100000 + 10;
#define ls ((p) << 1)
#define rs ((p) << 1 | 1)
int mul[MAXQ << 2];
SegmentTree() {}
void Update(int p) {
mul[p] = (long long int) mul[ls] * (long long int) mul[rs] % M;
}
void buildTree(int p, int l, int r) {
if (l == r) {
mul[p] = 1; return;
} int mid = (l + r) >> 1;
buildTree(ls, l, mid); buildTree(rs, mid + 1, r);
Update(p);
}
void Modify(int p, int l, int r, int pos, int k) {
if (l == r) {
mul[p] = k % M; return;
} int mid = (l + r) >> 1;
if (pos <= mid) Modify(ls, l, mid, pos, k);
else Modify(rs, mid + 1, r, pos, k);
Update(p);
}
int Query(int p, int l, int r, int ll, int rr) {
if (l == ll && rr == r) return mul[p];
int mid = (l + r) >> 1;
if (rr <= mid) return Query(ls, l, mid, ll, rr);
else if (mid + 1 <= ll) return Query(rs, mid + 1, r, ll, rr);
else return (long long int) Query(ls, l, mid, ll, mid)
* (long long int) Query(rs, mid + 1, r, mid + 1, rr) % M;
}
} segt;
int T;
int main() {
T = read();
while (T --> 0) {
Q = read(); M = read();
segt.buildTree(1, 1, Q);
for (int i = 1; i <= Q; ++i) {
int op = read(); int m = read();
if (op == 1) segt.Modify(1, 1, Q, i, m);
else segt.Modify(1, 1, Q, m, 1);
printf("%d
", segt.Query(1, 1, Q, 1, Q));
// for (int i = 1; i <= 20; ++i) printf("%d%c", segt.mul[i], i == 20 ? '
' : ' ');
}
}
return 0;
}