HDU Nice boat
题意:给定一个序列,两种操作,把一段变成x,把一段每个数字,如果他大于x,就变成他和x的gcd,求变换完后,最后的序列。
思路:线段树,每个结点多一个cover表示该位置以下区间是否数字全相同,然后每次延迟操作,最后输出的时候单点查询即可
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100005;
#define lson(x) ((x<<1)+1)
#define rson(x) ((x<<1)+2)
#define INF 0x3f3f3f3f
int t, n, num[N];
struct Node {
int l, r, x, setv;
bool cover;
} node[4 * N];
int gcd(int a, int b) {
if (!b) return a;
return gcd(b, a % b);
}
void pushup(int x) {
node[x].cover = ((node[lson(x)].x == node[rson(x)].x) && node[lson(x)].cover && node[rson(x)].cover);
node[x].x = node[lson(x)].x;
}
void build(int l, int r, int x = 0) {
node[x].l = l; node[x].r = r;
node[x].setv = -1;
node[x].cover = false;
if (l == r) {
node[x].cover = true;
node[x].x = num[l];
return;
}
int mid = (l + r) / 2;
build(l, mid, lson(x));
build(mid + 1, r, rson(x));
pushup(x);
}
void pushdown(int x) {
if (node[x].setv != -1) {
node[lson(x)].setv = node[rson(x)].setv = node[x].setv;
node[lson(x)].x = node[rson(x)].x = node[x].setv;
node[x].setv = -1;
}
}
void add1(int l, int r, int v, int x = 0) {
if (node[x].l >= l && node[x].r <= r) {
node[x].setv = v;
node[x].x = v;
return;
}
int mid = (node[x].l + node[x].r) / 2;
pushdown(x);
if (l <= mid) add1(l, r, v, lson(x));
if (r > mid) add1(l, r, v, rson(x));
pushup(x);
}
void add2(int l, int r, int v, int x = 0) {
if (node[x].cover && node[x].x <= v) return;
if (node[x].l >= l && node[x].r <= r && node[x].cover) {
node[x].x = gcd(node[x].x, v);
node[x].setv = node[x].x;
return;
}
pushdown(x);
int mid = (node[x].l + node[x].r) / 2;
if (l <= mid) add2(l, r, v, lson(x));
if (r > mid) add2(l, r, v, rson(x));
pushup(x);
}
int query(int k, int x = 0) {
if (node[x].l == node[x].r)
return node[x].x;
int mid = (node[x].l + node[x].r) / 2;
pushdown(x);
if (k <= mid) return query(k, lson(x));
if (k > mid) return query(k, rson(x));
}
int main() {
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &num[i]);
build(1, n);
int q;
scanf("%d", &q);
int c, a, b, v;
while (q--) {
scanf("%d%d%d%d", &c, &a, &b, &v);
if (c == 1)
add1(a, b, v);
else if (c == 2)
add2(a, b, v);
}
for (int i = 1; i <= n; i++)
printf("%d ", query(i));
printf("\n");
}
return 0;
}