大意:给你一个区间,每次可以进行两种操作,1:把区间中的数全都变成x 2:把区间中大于x的数变成gcd(a[i], x),最后输出序列。
思路:线段树成段更行,用num数组的叶子存储数据,节点当作lazy来使用。
1 #include <stdio.h> 2 const int maxn = 100005; 3 4 int num[maxn<<2]; 5 6 int gcd(int a, int b){ 7 return b?gcd(b, a%b):a; 8 } 9 10 void PushUp(int id){ 11 if(num[id<<1] == num[id<<1|1]){ 12 num[id] = num[id<<1]; 13 } 14 } 15 16 void PushDown(int id){ 17 if(num[id] != -1){ 18 num[id<<1] = num[id<<1|1] = num[id]; 19 num[id] = -1; 20 } 21 } 22 23 void Build(int l, int r, int id){ 24 num[id] = -1; 25 if(l == r){ 26 scanf("%d", &num[id]); 27 return ; 28 } 29 int mid = (l+r)>>1; 30 Build(l, mid, id<<1); 31 Build(mid+1, r, id<<1|1); 32 PushUp(id); 33 } 34 35 36 void Update(int op, int L, int R, int t, int l, int r, int id){ 37 if(op == 1){ 38 if(L <= l && r <= R){ 39 num[id] = t; 40 return ; 41 } 42 } 43 else if(op == 2){ 44 if(L <= l && r <= R && num[id] != -1){ 45 if(num[id] > t){ 46 num[id] = gcd(num[id], t); 47 } 48 return ; 49 } 50 } 51 PushDown(id); 52 int mid = (l+r)>>1; 53 if(L <= mid){ 54 Update(op, L, R, t, l, mid, id<<1); 55 } 56 if(R > mid){ 57 Update(op, L, R, t, mid+1, r, id<<1|1); 58 } 59 PushUp(id); 60 } 61 62 void Query(int l, int r, int id){ 63 if(l == r){ 64 printf("%d ", num[id]); 65 return ; 66 } 67 PushDown(id); 68 int mid = (l+r)>>1; 69 Query(l, mid, id<<1); 70 Query(mid+1, r, id<<1|1); 71 } 72 73 int T, n, m; 74 75 int main() 76 { 77 scanf("%d", &T); 78 while(T--){ 79 scanf("%d", &n); 80 Build(1, n, 1); 81 scanf("%d", &m); 82 while(m--){ 83 int op, a, b, c; 84 scanf("%d%d%d%d", &op, &a, &b, &c); 85 Update(op, a, b, c, 1, n, 1); 86 } 87 Query(1, n, 1); 88 puts(""); 89 } 90 91 return 0; 92 }
HDU 4902
HDU 4902 Nice boat(线段树 区间更新),布布扣,bubuko.com
时间: 2024-10-05 07:18:10