Time Limit: 30000/15000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
There are n numbers a_1,a_2,...,a_n on a line, everytime you can change every number in a segment [l,r] into a number x(type 1), or change every number a_i in a segment [l,r] which is bigger than x to gcd(a_i,x) (type 2).
You should output the final sequence.
Input
The first line contains an integer T, denoting the number of the test cases.
For each test case, the first line contains a integers n.
The next line contains n integers a_1,a_2,...,a_n separated by a single space.
The next line contains an integer Q, denoting the number of the operations.
The next Q line contains 4 integers t,l,r,x. t denotes the operation type.
T<=2,n,Q<=100000
a_i,x >=0
a_i,x is in the range of int32(C++)
For each test case, the first line contains a integers n.
The next line contains n integers a_1,a_2,...,a_n separated by a single space.
The next line contains an integer Q, denoting the number of the operations.
The next Q line contains 4 integers t,l,r,x. t denotes the operation type.
T<=2,n,Q<=100000
a_i,x >=0
a_i,x is in the range of int32(C++)
Output
For each test case, output a line with n integers separated by a single space representing the final sequence.
Please output a single more space after end of the sequence
Please output a single more space after end of the sequence
Sample Input
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
16807 937186357 937186357 937186357 937186357 1 1 1624379149 1624379149 1624379149
//828MS 1972K
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define lch(x) ((x)<<1)
#define rch(x) ((x)<<1 | 1)
using namespace std;
const int maxn = 100000;
int num[maxn+5];
int tree[maxn<<2];
bool flag[maxn<<2];
int gcd(int x, int y){
return y == 0 ? x : gcd(y, x%y);
}
void build(int n, int l, int r){
flag[n] = false; //所有节点标记置0
if(l == r){
tree[n] = num[l];
return;
}
int mid = (l + r) >> 1;
build(lch(n), l, mid);
build(rch(n), mid+1, r);
}
void push_down(int n){
if(flag[n]){ //有标记才下传
flag[lch(n)] = flag[rch(n)] = true;
tree[lch(n)] = tree[rch(n)] = tree[n];
flag[n] = false;
}
}
void seg_set(int a, int b, int v, int n, int l, int r){
if(a <= l && r <= b){
tree[n] = v;
flag[n] = true;
return;
}
push_down(n); //区间[l, r]没有完全被[a, b]覆盖,则需要尝试标记下传
int mid = (l + r) >> 1;
if(b <= mid) seg_set(a, b, v, lch(n), l, mid); //抛弃右段
else if(mid+1 <= a) seg_set(a, b, v, rch(n), mid+1, r); //抛弃左段
else {
seg_set(a, b, v, lch(n), l, mid);
seg_set(a, b, v, rch(n), mid+1, r);
}
}
void modify(int a, int b, int x, int n, int l, int r){
if(flag[n] && a <= l && r <= b){ //边界1:到了标记节点且该节点对应的区间被完全覆盖
if(tree[n] > x) tree[n] = gcd(tree[n], x);
return;
}
if(l == r){ //边界2:到了叶子节点
if(tree[n] > x) tree[n] = gcd(tree[n], x);
return;
}
push_down(n);
int mid = (l + r) >> 1;
if(b <= mid) modify(a, b, x, lch(n), l, mid); //抛弃右段
else if(mid+1 <= a) modify(a, b, x, rch(n), mid+1, r); //抛弃左段
else {
modify(a, b, x, lch(n), l, mid);
modify(a, b, x, rch(n), mid+1, r);
}
}
void print(int a, int b, int n, int l, int r){
if(flag[n]){ //边界1:到了标记节点
for(int i=l; i<=r; i++) printf("%d ", tree[n]);
return;
}
if(l == r){ //边界2:到了叶子节点
printf("%d ", tree[n]);
return;
}
int mid = (l+r)>>1;
print(a, b, lch(n), l, mid);
print(a, b, rch(n), mid+1, r);
}
int main(){
int T; scanf("%d", &T);
while(T--){
int n, Q;
scanf("%d", &n);
for(int i=1; i<=n; i++)
scanf("%d", &num[i]);
build(1, 1, n);
scanf("%d", &Q);
while(Q--){
int t, l, r, x;
scanf("%d%d%d%d", &t, &l, &r, &x);
if(t == 1) seg_set(l, r, x, 1, 1, n);
else modify(l, r, x, 1, 1, n);
}
print(1, n, 1, 1, n);
printf("\n");
}
return 0;
}