一、内容

题意: 有一个初始值为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;
}