Problem E. TeaTree

ps:对每个Value都开一个线段树,线段树的叶子节点的值表示的是这个Value的约数,什么意思呢?叶子节点的编号和Value的约数是一一对应的,然后区间维护最大值,是不是非常非常暴力,最后从底向上合并线段树(因为树的每个节点都开了一个线段树),注意要动态开点!!!

官方题解:

inline void upd(int &x, int y) { x < y && (x = y); }

const int N = 100005;

int n, tot, cnt;
int head[N], ans[N], root[N], ls[400 * N], rs[400 * N], sum[400 * N];

struct node { int to, next; } G[N];

vector<int> d[N];

void Inite() {
    cnt = tot = 0;
    mem(head, -1);
    for (int i = 1; i < N; ++i) for (int j = 1; i * j < N; ++j) d[i * j].pb(i);
}

void addedge(int u, int v) {
    G[tot].to = v, G[tot].next = head[u], head[u] = tot++;
}

void Pushup(int rt) {
    if (ls[rt] && rs[rt]) sum[rt] = max(sum[ls[rt]], sum[rs[rt]]);
    else if (ls[rt]) sum[rt] = sum[ls[rt]];
    else if (rs[rt]) sum[rt] = sum[rs[rt]];
}

int Merge(int x, int y, int& res) {
    if (!x || !y) return x ^ y;
    if (sum[x] == sum[y]) res = max(res, sum[x]);
    ls[x] = Merge(ls[x], ls[y], res);
    rs[x] = Merge(rs[x], rs[y], res);
    Pushup(x);
    return x;
}

void DFS(int u) {
    ans[u] = -1;
    for (int i = head[u]; ~i; i = G[i].next) {
        DFS(G[i].to);
        root[u] = Merge(root[u], root[G[i].to], ans[u]);
    }
}

void Update(int l, int r, int &rt, int pos) {
    if (!rt) rt = ++cnt;
    if (l == r) {
        sum[rt] = pos;
        return;
    }
    int mid = (l + r) >> 1;
    if (pos <= mid) Update(l, mid, ls[rt], pos);
    else Update(mid + 1, r, rs[rt], pos);
    Pushup(rt);
}

int main()
{
    Inite();

    sc(n);
    Rep(i, 2, n) {
        int x;
        sc(x);
        addedge(x, i);
    }

    Rep(i, 1, n) {
        int x;
        sc(x);
        root[i] = 0;
        rep(j, 0, Size(d[x])) Update(1, N - 1, root[i], d[x][j]);
    }

    DFS(1);
    Rep(i, 1, n) pr(ans[i]);

    return 0;
}

 

posted @ 2018-08-24 13:15  天之道,利而不害  阅读(307)  评论(0编辑  收藏  举报