题目链接:https://ac.nowcoder.com/acm/contest/877/F
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述
输入描述

输出描述

输入

4
5 45 20 65
7
1 1 4
0 1 4
1 1 4
1 3 4
0 3 4
1 3 4
1 2 2

输出

5
2
4
2
6

解题思路

题意:有两种操作:0代表将[l, r]之间的数变成√ai, 1代表求出[l, r]中所有数的最大公约数。
思路:线段数,因为1开根号还是1,故可以把结果为1的标记上,避免无用的计算。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200005;
struct edge {
    bool Mark;
    long long val;
}segTree[MAXN << 2];
void Create(int root, int left, int right) {
    segTree[root].Mark = 0;
    if (left == right) {
        scanf("%lld", &segTree[root].val);
        return ;
    }
    int mid = left + ((right - left) >> 1);
    Create(root << 1, left, mid);
    Create(root << 1 | 1, mid + 1, right);
    segTree[root].Mark = segTree[root << 1].Mark && segTree[root << 1 | 1].Mark;
    segTree[root].val = __gcd(segTree[root << 1].val, segTree[root << 1 | 1].val);
}
void Update(int root, int Q_left, int Q_right, int left, int right) {
    if (segTree[root].Mark)
        return ;
    if (left == right) {
        segTree[root].val = sqrt(segTree[root].val);
        if (segTree[root].val == 1)
            segTree[root].Mark = 1;
        return ;
    }
    int mid = left + ((right - left) >> 1);
    if (Q_right <= mid)
        Update(root << 1, Q_left, Q_right, left, mid);
    else if (Q_left > mid)
        Update(root << 1 | 1, Q_left, Q_right, mid + 1, right);
    else {
        Update(root << 1, Q_left, mid, left, mid);
        Update(root << 1 | 1, mid + 1, Q_right, mid + 1, right);
    }
    segTree[root].Mark = segTree[root << 1].Mark && segTree[root << 1 | 1].Mark;
    segTree[root].val = __gcd(segTree[root << 1].val, segTree[root << 1 | 1].val);
}
long long Query_(int root, int Q_left, int Q_right, int left, int right) {
    if (Q_left <= left && Q_right >= right)
        return segTree[root].val;
    int mid = left + ((right - left) >> 1);
    if (Q_right <= mid)
        return Query_(root << 1, Q_left, Q_right, left, mid);
    else if (Q_left > mid)
        return Query_(root << 1 | 1, Q_left, Q_right, mid + 1, right);
    else return __gcd(Query_(root << 1, Q_left, mid, left, mid),
            Query_(root << 1 | 1, mid + 1, Q_right, mid + 1, right));
}
int main() {
    int n, m, left, right, Judge;
    scanf("%d", &n);
    Create(1, 1, n);
    scanf("%d", &m);
    while (m--) {
        scanf("%d%d%d", &Judge, &left, &right);
        if (Judge)
            printf("%lld\n", Query_(1, left, right, 1, n));
        else Update(1, left, right, 1, n);
    }
    return 0;
}