Time Limit: 30000/15000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 146 Accepted Submission(s): 75
题意:给定一个数字序列,对其进行两种操作:1、将序列中连续的一段变成一样的数x;2、给序列中连续的一段和一个数x,对于这个连续一段中的每个数,如果小于x则取x与这个数的最大公约数,否则不操作。
题解:线段树+懒人标记
代码:
1 #include <cstdio> 2 #include <cstring> 3 4 const int LEN = 400040; 5 6 struct line 7 { 8 int left; 9 int right; 10 int value; 11 }line[LEN*2]; 12 int point[LEN*2]; //记录线段树底层节点的位置 13 14 inline int gcd(int a,int b) //求最大公约数 15 { 16 return a % b ? gcd(b, a % b) : b; 17 } 18 19 void buildt(int left, int right, int step) //建树同时初始化懒惰标记 20 { 21 line[step].value = -1; 22 line[step].left = left; 23 line[step].right = right; 24 if (left == right){ 25 point[left] = step; 26 return; 27 } 28 int mid = (left + right) / 2; 29 buildt(left, mid, step*2); 30 buildt(mid+1, right, step*2+1); 31 } 32 33 void query_1(int left, int right, int x, int step) //操作一 34 { 35 if (left == line[step].left && right == line[step].right){ 36 line[step].value = x; 37 return; 38 } 39 if (line[step].value != -1){ 40 line[step*2].value = line[step*2+1].value = line[step].value; 41 line[step].value = -1; 42 } 43 int mid = (line[step].left + line[step].right) / 2; 44 if (right <= mid) 45 query_1(left, right, x, step*2); 46 else if (left > mid) 47 query_1(left, right, x, step*2+1); 48 else{ 49 query_1(left, mid, x, step*2); 50 query_1(mid+1, right, x, step*2+1); 51 } 52 } 53 54 void query_2(int left, int right, int x, int step) //操作函数二 55 { 56 if (line[step].left == left && line[step].right == right){ 57 if (line[step].value != -1){ //如果找到对应区间,且有标记,则进行条件判断,否则继续 58 if (line[step].value > x) 59 line[step].value = gcd(line[step].value, x); 60 return; 61 } 62 } 63 if (line[step].value != -1){ //如果改点被标记,则下移一层 64 line[step*2].value = line[step*2+1].value = line[step].value; 65 line[step].value = -1; 66 } 67 int mid = (line[step].left + line[step].right) / 2; 68 if (right <= mid) 69 query_2(left, right, x, step*2); 70 else if (left > mid) 71 query_2(left, right, x, step*2+1); 72 else{ 73 query_2(left, mid, x, step*2); 74 query_2(mid+1, right, x, step*2+1); 75 } 76 } 77 78 void findans(int left, int right, int step) //dfs输出结果 79 { 80 if (line[step].left == left && line[step].right == right){ 81 if (line[step].value != -1){ 82 for(int i = 0; i < line[step].right - line[step].left + 1; i++) 83 printf("%d ", line[step].value); 84 return; 85 } 86 } 87 if (line[step].value != -1){ 88 line[step*2].value = line[step*2+1].value = line[step].value; 89 line[step].value = -1; 90 } 91 int mid = (line[step].left + line[step].right) / 2; 92 if (right <= mid) 93 findans(left, right, step*2); 94 else if (left > mid) 95 findans(left, right, step*2+1); 96 else{ 97 findans(left, mid, step*2); 98 findans(mid+1, right, step*2+1); 99 } 100 } 101 102 int main() 103 { 104 int T; 105 //freopen("in.txt", "r", stdin); 106 scanf("%d", &T); 107 while(T--){ 108 int n; 109 memset(point, 0, sizeof(point)); 110 scanf("%d", &n); 111 buildt(1, n, 1); 112 for(int i = 1; i <= n; i++){ 113 int t; 114 scanf("%d", &t); 115 line[point[i]].value = t; 116 } 117 int m; 118 scanf("%d", &m); 119 for(int i = 0; i < m; i++){ 120 int t, l, r, x; 121 scanf("%d %d %d %d", &t, &l, &r, &x); 122 if (t == 1){ 123 query_1(l, r, x, 1); 124 } 125 else if (t == 2){ 126 query_2(l, r, x, 1); 127 } 128 } 129 findans(1, n, 1); 130 printf("\n"); 131 } 132 return 0; 133 }