• 2018 Multi-University Training Contest 10


    权值线段树合并

    线段树维护1~1e5这个值域,对于每个点开一颗线段树,储存值域内最大的因数。

    然后对整个树dfs,合并父亲和儿子节点的线段树,在合并过程中更新答案。

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define full(a, b) memset(a, b, sizeof a)
    #define FAST_IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
    using namespace std;
    typedef long long ll;
    inline int lowbit(int x){ return x & (-x); }
    inline int read(){
        int ret = 0, w = 0; char ch = 0;
        while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
        while(isdigit(ch)) ret = (ret << 3) + (ret << 1) + (ch ^ 48), ch = getchar();
        return w ? -ret : ret;
    }
    inline int gcd(int a, int b){ return b ? gcd(b, a % b) : a; }
    inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
    template <typename T>
    inline T max(T x, T y, T z){ return max(max(x, y), z); }
    template <typename T>
    inline T min(T x, T y, T z){ return min(min(x, y), z); }
    template <typename A, typename B, typename C>
    inline A fpow(A x, B p, C lyd){
        A ans = 1;
        for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
        return ans;
    }
    const int N = 100005;
    int n, cnt, tot, head[N], w[N], tree[(N*400)<<2], ls[(N*400)<<2], rs[(N*400)<<2], root[N], res[N];
    struct Edge{ int v, next; }edge[N<<1];
    vector<int> fac[N];
    
    void calc(int x){
        if(!fac[x].empty()) return;
        fac[x].push_back(1), fac[x].push_back(x);
        for(int i = 2; i <= sqrt(x) + 0.5; i ++){
            if(x % i == 0){
                fac[x].push_back(i), fac[x].push_back(x / i);
            }
        }
    }
    
    int build(){
       tot ++;
       tree[tot] = ls[tot] = rs[tot] = 0;
       return tot;
    }
    
    void addEdge(int a, int b){
        edge[cnt].v = b, edge[cnt].next = head[a], head[a] = cnt ++;
    }
    
    void push_up(int rt){
        tree[rt] = max(tree[ls[rt]], tree[rs[rt]]);
    }
    
    void insert(int rt, int l, int r, int val){
        if(l == r){
            tree[rt] = l;
            return;
        }
        int mid = (l + r) >> 1;
        if(val <= mid){
            if(!ls[rt]) ls[rt] = build();
            insert(ls[rt], l, mid, val);
        }
        if(val > mid){
            if(!rs[rt]) rs[rt] = build();
            insert(rs[rt], mid + 1, r, val);
        }
        push_up(rt);
    }
    
    int merge(int p, int q, int l, int r, int &ans){
        if(!p || !q) return p ^ q;
        if(tree[p] == tree[q]) ans = max(ans, tree[p]);
        if(l == r){
            tree[p] = max(tree[p], tree[q]);
            return p;
        }
        int mid = (l + r) >> 1;
        ls[p] = merge(ls[p], ls[q], l, mid, ans);
        rs[p] = merge(rs[p], rs[q], mid + 1, r, ans);
        push_up(p);
        return p;
    }
    
    void dfs(int s, int fa){
        res[s] = -1;
        for(int i = head[s]; i != -1; i = edge[i].next){
            int u = edge[i].v;
            if(u == fa) continue;
            dfs(u, s);
            root[s] = merge(root[s], root[u], 1, N, res[s]);
        }
    }
    
    int main(){
        
        full(head, -1);
        n = read();
        for(int i = 2; i <= n; i ++){
            int v = read();
            addEdge(v, i), addEdge(i, v);
        }
        for(int i = 1; i <= n; i ++) w[i] = read();
        for(int i = 1; i <= n; i ++) calc(w[i]);
        for(int i = 1; i <= n; i ++){
            root[i] = build();
            for(int j = 0; j < fac[w[i]].size(); j ++){
                insert(root[i], 1, N, fac[w[i]][j]);
            }
        }
        dfs(1, 0);
        for(int i = 1; i <= n; i ++){
            printf("%d
    ", res[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    【20220924】双减(上)
    【20220920】连岳摘抄
    【20220918】周日的忧伤
    【20220919】连岳摘抄
    【20220922】连岳摘抄
    【20220925】双减(下)
    【20220926】人精鬼灵
    Vue Promise (回调地狱)
    Vue ES6模块化语法学习
    Vue async、await 的使用注意事项
  • 原文地址:https://www.cnblogs.com/onionQAQ/p/11170307.html
Copyright © 2020-2023  润新知