一 问题描述
有 N 个数,a1,a2,an,每次都可以将[l,r]区间的每个数字都更改为数字 x,或将[l,r]区间每个大于 x 的 ai 都更改为最大公约数 gcd(ai,x),请输出最后的序列。
二 输入和输出
1 输入
第 1 行包含一个整数T,表示测试用例的数量。每个测试用例的第 1 行都包含整数 n,下一行包含以空格分隔的 n 个整数 a1,a2,an,再下一行包含一个整数 Q,表示操作数量。下面的 Q 行,每行都包含四个整数 t、l、 r、 x,t 表示操作类型,l,r 表示出现左右端点。
2 输出
对每个测试用例,都单行输出以空格分隔的最终序列。
三 输入和输出样例
1 输入样例
1
10
16807 282475249 1622650073 984943658 1144108930 470211272 101027544 1457850878 1458777923 2007237709
10
1 3 6 74243042
2 4 8 16531729
1 3 4 1474833169
2 1 8 1131570933
2 7 9 1505795335
2 3 7 101929267
1 4 10 1624379149
2 2 8 2110010672
2 6 7 156091745
1 2 5 937186357
2 输出样例
16807 937186357 937186357 937186357 937186357 1 1 1624379149 1624379149 1624379149
四 分析和设计
1 分析
本问题很明显是区间更新问题,但不仅仅是简单的区间更新,而是将 [l,r] 区间的每个大于 x 的 ai 都更改为 gcd(ai,x)。
2 设计
a 创建线段数
b 区间更新,将 [l,r] 区间的每个数字都更改为数字 x
c 区间更新,将 [l,r] 区间的每个大于 x 的 ai 都更改为 gcd(ai,x)。
五 代码
package com.platform.modules.alg.alglib.hdu4902;
public class Hdu4902 {
private int N = 100005;
private int a[] = new int[N];
private int maxs[] = new int[N << 2];
private int lazy[] = new int[N << 2];
private int n;
private int m;
public String output = "";
// 最大公约数
int gcd(int a, int b) {
if (b == 0) return a;
else return gcd(b, a % b);
}
// 上传
void PushUp(int i) {
maxs[i] = Math.max(maxs[i << 1], maxs[i << 1 | 1]);
}
// 下传
void PushDown(int i) {
if (lazy[i] != 0) {
lazy[i << 1] = lazy[i << 1 | 1] = lazy[i];
maxs[i << 1] = maxs[i << 1 | 1] = maxs[i];
lazy[i] = 0;
}
}
// 建线段树
void build(int l, int r, int i) {
if (l == r) {
lazy[i] = a[l];
maxs[i] = lazy[i];
return;
}
int mid = (l + r) >> 1;
build(l, mid, i << 1);
build(mid + 1, r, i << 1 | 1);
PushUp(i);
}
// 类型1更新
void update1(int x, int L, int R, int l, int r, int i) {
if (L <= l && r <= R) {
lazy[i] = maxs[i] = x;
return;
}
PushDown(i);
int mid = (l + r) >> 1;
if (L <= mid)
update1(x, L, R, l, mid, i << 1);
if (R > mid)
update1(x, L, R, mid + 1, r, i << 1 | 1);
PushUp(i);
}
// 类型2更新
void update2(int x, int L, int R, int l, int r, int i) {
if (maxs[i] <= x) return;
if (lazy[i] != 0 && L <= l && r <= R) {
lazy[i] = gcd(lazy[i], x);
maxs[i] = lazy[i];
return;
}
PushDown(i);
int mid = (l + r) >> 1;
if (L <= mid)
update2(x, L, R, l, mid, i << 1);
if (R > mid)
update2(x, L, R, mid + 1, r, i << 1 | 1);
PushUp(i);
}
void print(int l, int r, int i) {
if (l == r) {
output += lazy[i] + " ";
return;
}
PushDown(i);
int mid = (l + r) >> 1;
print(l, mid, i << 1);
print(mid + 1, r, i << 1 | 1);
}
public String cal(String input) {
int l, r, opt;
int x;
String[] line = input.split("\n");
n = Integer.parseInt(line[0]);
String[] nums = line[1].split(" ");
for (int i = 1; i <= n; i++)
a[i] = Integer.parseInt(nums[i - 1]);
build(1, n, 1);
m = Integer.parseInt(line[2]);
int j = 0;
while (m-- > 0) {
String[] command = line[3 + j].split(" ");
j++;
opt = Integer.parseInt(command[0]);
l = Integer.parseInt(command[1]);
r = Integer.parseInt(command[2]);
x = Integer.parseInt(command[3]);
if (opt == 1) update1(x, l, r, 1, n, 1);
else update2(x, l, r, 1, n, 1);
}
print(1, n, 1);
return output;
}
}