Codeforces Round #264 (Div. 2) E. Caisa and Tree

 

修改操作只有 50 次,最多就只有 $O(50)$ 段查询,每段查询 dfs 一遍统计答案即可。

查询的是一个节点到其根路径上的节点的值,那么就 dfs 进入这个点就把这个点的值加入栈中,离开这个点就把它的值 pop 掉。具体查询方法就是对每种质因子都开一个栈,然后进入一个点就分解它的值,取每种质因子栈顶的节点,取深度最大的节点即可。

#include 
#define pii pair

const int N = 1e5 + 7;
const int W = 2e6 + 7;

int prime[N], prin;
bool vis[N];

void init() {
    static const int XN = sqrt(W + 0.5);
    for (int i = 2; i < XN; i++) {
        if (!vis[i]) prime[++prin] = i;
        for (int j = 1; j <= prin && i * prime[j] < XN; j++) {
            vis[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
}

int a[N], head[N], cnt = 1, n, q, ans[N];
struct E {
    int v, ne;
} e[N << 1];

void add(int u, int v) {
    e[++cnt].v = v; e[cnt].ne = head[u]; head[u] = cnt;
    e[++cnt].v = u; e[cnt].ne = head[v]; head[v] = cnt;
}

struct QUERY {
    int opt, x, y;
} que[N];

std::vector<int> vec[W], query[N];
int dep[N];

void dfs1(int u, int f) {
    dep[u] = dep[f] + 1;
    for (int i = head[u]; i; i = e[i].ne) {
        int v = e[i].v;
        if (v == f) continue;
        dfs1(v, u);
    }
}

int max(int a, int b) {
    return dep[a] > dep[b] ? a : b;
}

void dfs(int u, int f) {
    int w = a[u];
    int res = 0;
    for (int i = 1; i <= prin; i++) {
        if (w % prime[i] == 0) {
            if (!vec[prime[i]].empty()) {
                res = max(vec[prime[i]][vec[prime[i]].size() - 1], res);
                assert(vec[prime[i]][vec[prime[i]].size() - 1] != u);
            }
            vec[prime[i]].push_back(u);
            while (w % prime[i] == 0) w /= prime[i];
        }
    }
    if (w > 1) {
        if (!vec[w].empty()) res = max(vec[w][vec[w].size() - 1], res);
        vec[w].push_back(u);
    }
    for (int id : query[u])
        ans[id] = res;
    for (int i = head[u]; i; i = e[i].ne) {
        int v = e[i].v;
        if (v == f) continue;
        dfs(v, u);
    }
    w = a[u];
    for (int i = 1; i <= prin; i++) {
        if (w % prime[i] == 0) {
            assert(vec[prime[i]][vec[prime[i]].size() - 1] == u);
            vec[prime[i]].pop_back();
            while (w % prime[i] == 0) w /= prime[i];
        }
    }
    if (w > 1) vec[w].pop_back();
    query[u].clear();
}

int main() {
    init();
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; i++)
        scanf("%d", a + i);
    for (int i = 1, x, y; i < n; i++) {
        scanf("%d%d", &x, &y);
        add(x, y);
    }
    dfs1(1, 0);
    int tol = 0;
    for (int i = 1; i <= q; i++) {
        scanf("%d%d", &que[i].opt, &que[i].x);
        if (que[i].opt == 2)
            scanf("%d", &que[i].y), tol++;
        ans[i] = -2;
    }
    tol = q - tol;
    for (int i = 1; i <= q; ) {
        while (i <= q && que[i].opt == 2) {
            a[que[i].x] = que[i].y;
            i++;
        }
        while (i <= q && que[i].opt == 1) {
            query[que[i].x].push_back(i);
            i++;
        }
        dfs(1, 0);
    }
    for (int i = 1; i <= q; i++)
        if (ans[i] != -2)
            printf("%d\n", ans[i] == 0 ? -1 : ans[i]), tol--;
    assert(tol == 0);
    return 0;
}
View Code

 

你可能感兴趣的:(Codeforces Round #264 (Div. 2) E. Caisa and Tree)