U135884 膜法问题 TJ

题目链接

思路1

可以发现,模的值呈周期性,一个周期 \(a \times b\) 个值。
如果 \(a \times b \le r -l.\) 那么直接输出周期里的最大值即可。
否则的话,就要查找区间 \(l \mod (a \times b) ~-~ r \mod (a \times b).\) 里的最大值了。
注意:当 \(r \mod (a \times b) < l \mod (a \times b)\) 时,查找 \(0 ~-~ r \mod (a \times b)\)\(l \mod (a \times b) ~-~ (a \times b - 1).\)
可以使用线段树。

代码1

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXK = 1e5 + 10;
const int MAXNM = 1e6 + 10;
int a ,b ,k ,n = 0 ,qu;
int t[MAXNM] ,maxl = 0;
struct node {
	int maxn ,l ,r;
	node () {
		maxn = 0;
	}
}tree[MAXNM << 2];
void pushup (int i) {
	tree[i].maxn = max (tree[i << 1].maxn ,tree[i << 1 | 1].maxn);
	return ;
}
void build (int i ,int l ,int r) {
	tree[i].l = l ,tree[i].r = r;
	if (l == r) {
		tree[i].maxn = t[l];
		return ;
	}
	int mid = (l + r) >> 1;
	build (i << 1 ,l ,mid);
	build (i << 1 | 1 ,mid + 1 ,r);
	pushup (i);
	return ;
}
int query (int i ,int l ,int r) {
	if (tree[i].l >= l && tree[i].r <= r) {
		return tree[i].maxn;
	}
	int MAXL = 0;
	if (tree[i << 1].r >= l) MAXL = query (i << 1 ,l ,r);
	if (tree[i << 1 | 1].l <= r) MAXL = max (MAXL ,query (i << 1 | 1 ,l ,r));
	return MAXL;
}
int main () {
	scanf ("%d%d%d",&a ,&b ,&k);
	qu = a * b;
	for (int q = 0;q < qu;++ q)
		t[q] = (q % a) + (q % b) ,maxl = max (maxl ,t[q]);
	build (1 ,0 ,qu - 1);
	int l ,r;
	for (int q = 1;q <= k;++ q) {
		scanf ("%d%d",&l ,&r);
		if (qu <= r - l) printf ("%d\n",maxl);
		else {
			l = l % qu; r = r % qu;
			if (l <= r)
				printf ("%d\n",query (1 ,l ,r));
			else printf ("%d\n",max (query (1 ,l ,qu - 1) ,query (1 ,0 ,r)));
		}
	}
	return 0;
}

思路2

普及没学过线段树,直接 \(ST\) 表往上怼。

代码2

自己写吧(主要是我写挂了)。。。

posted @ 2020-11-01 16:49  tuscjaf  阅读(48)  评论(0编辑  收藏  举报