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
自己写吧(主要是我写挂了)。。。
cb