[CF438D]The Child and Sequence

题目大意:给定一个数列,三个操作:

  1. $1;l;r:$输出区间$[l,r]$的和
  2. $2;l;r;x:$区间$[l,r]$对$x$取模
  3. $3;p;x:$把$p$的值修改成$x$

题解:线段树,发现对于取模操作,若模数大于被膜数,则不会有影响,可以通过维护最大值跳过,若是对有影响,那么这个数字一定至少会变成原来的一半,所以一个数最多更改$log_2$次,可以承受。

卡点:我$max$函数写成$min$

C++ Code:

#include <cstdio>
#define maxn 100010
int s[maxn];
inline int max(int a, int b) {return a > b ? a : b;}
namespace Segment_Tree {
	int n;
	long long V[maxn << 2];
	int M[maxn << 2];
	inline update(int rt) {
		M[rt] = max(M[rt << 1], M[rt << 1 | 1]);
		V[rt] = V[rt << 1] + V[rt << 1 | 1];
	}
	void build(int rt = 1, int l = 1, int r = n) {
		if (l == r) {
			M[rt] = V[rt] = s[l];
			return ;
		}
		int mid = l + r >> 1;
		build(rt << 1, l, mid);
		build(rt << 1 | 1, mid + 1, r);
		update(rt);
	}
	int L, R, p, x;
	void ___add(int rt, int l, int r) {
		if (l == r) {
			V[rt] = M[rt] = x;
			return ;
		}
		int mid = l + r >> 1;
		if (p <= mid) ___add(rt << 1, l, mid);
		else ___add(rt << 1 | 1, mid + 1, r);
		update(rt);
	}
	inline void add(int pos, int X) {
		p = pos, x = X;
		___add(1, 1, n);
	}
	void __add(int rt, int l, int r) {
		if (M[rt] < x) return ;
		if (l == r) {
			V[rt] = M[rt] = V[rt] % x;
			return ;
		}
		int mid = l + r >> 1;
		if (L <= mid) __add(rt << 1, l, mid);
		if (R > mid) __add(rt << 1 | 1, mid + 1, r);
		update(rt);
	}
	inline void add(int ll, int rr, int X) {
		L = ll, R = rr, x = X;
		__add(1, 1, n);
	}
	long long __ask(int rt, int l, int r) {
		if (L <= l && R >= r) return V[rt];
		int mid = l + r >> 1; long long ans = 0;
		if (L <= mid) ans = __ask(rt << 1, l, mid);
		if (R > mid) ans = ans + __ask(rt << 1 | 1, mid + 1, r);
		return ans;
	}
	inline long long ask(int ll, int rr) {
		L = ll, R = rr;
		return __ask(1, 1, n);
	}
}
using Segment_Tree::add;
using Segment_Tree::ask;
int n, m;
int main() {
	scanf("%d%d", &n, &m); Segment_Tree::n = n;
	for (int i = 1; i <= n; i++) scanf("%d", s + i);
	Segment_Tree::build();
	while (m --> 0) {
		int op, l, r, val;
		scanf("%d%d%d", &op, &l, &r);
		if (op == 1) {
			printf("%lld
", ask(l, r));
		} else if (op == 2) {
			scanf("%d", &val);
			add(l, r, val);
		} else add(l, r);
	}
	return 0;
} 

  

原文地址:https://www.cnblogs.com/Memory-of-winter/p/9762562.html