ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Square Tree

2022-07-31 22:32:50  阅读:177  来源: 互联网

标签:rt Square return rs int tree Tree leq


Square Tree

题目链接: [Square Tree](SquareTree (nowcoder.com))

题目描述:给你一棵\(n\)个节点的树,根节点为\(1\)。初始时所有结点的权值都为\(1\)。给你\(m\)次操作,每次操作给你三个数\(u , v , w\),其含义为:若节点\(x\),其子树中含从\(u\)到\(v\)的路径中的节点,则将节点\(x\)的权值乘以\(w\)。\(m\)次操作后,给\(Q\)个询问,每个询问给定一个节点编号\(x\),若节点\(x\)的权值是完全平方数,则输出YES,否则输出NO

数据范围:\(1 \leq n \leq 2 \times 10^5 , 1 \leq m \leq 2 \times 10^5 , 1 \leq Q \leq 2 \times 10^5 , 1 \leq w \leq 100\)。

思路:首先不管树上操作,先来看如何判断是否为完全平方数,显然要判断其表示成质因数乘积的形式的时候,其所有质因数的幂次是否为偶数,若是,则YES,否则NO。考虑到\(1 \leq w \leq 100\),所以我们可以将所有质因数求出来,重新编号,进行状压,因为只需要考虑奇偶性,所以乘法就变成异或运算。再来看操作是怎样完成的。

对于如图所示的一棵树,假设当前给定的操作的\(u = 4 , v = 5\),那么显然要更新两条路径:\(u \to v\)和\(lca(u , v) \to 1\)但不包括\(lca(u , v)\)。但考虑到判断平方数,对一个数乘同一个数三次和乘一次,其是否为平方数的性质不会发生改变,所以实际要对\(u \to v\) , \(lca(u ,v) \to 1\),\(lca(u , v) \to lca(u , v)\)这三条路径上的点都乘以权值,也即都与转化后的权值进行异或运算。在询问的时候,我们只需要查询该点最终值是否为\(0\)即可。对于树上链的更新,是比较明显的树链剖分。

时间复杂度:\(O(nlogn + mlog^2n + qlogn)\)

参考代码:

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
using ll = long long;
struct segmentTree {
    int lr, rs, mid;
    ll tag;
};
const int N = 2e5 + 5;
segmentTree tree[N << 2];
unordered_map<int, int>mp;
vector<int>pri;
void pushDown(int rt) {
    if (tree[rt].tag == 0) return;
    tree[rt << 1].tag ^= tree[rt].tag;
    tree[rt << 1 | 1].tag ^= tree[rt].tag;
    tree[rt].tag = 0;
    return;
}
void buildTree(int rt, int lr, int rs) {
    tree[rt].lr = lr; tree[rt].rs = rs;
    if (lr == rs) return;
    int mid = tree[rt].mid = lr + rs >> 1;
    buildTree(rt << 1, lr, mid);
    buildTree(rt << 1 | 1, mid + 1, rs);
    return;
}
void update(int rt, int lr, int rs, ll val) {
    if (tree[rt].lr > rs || tree[rt].rs < lr) return;
    if (tree[rt].lr >= lr && tree[rt].rs <= rs) {
        tree[rt].tag ^= val;
        return;
    }
    pushDown(rt);
    if (tree[rt].mid >= lr) update(rt << 1, lr, rs, val);
    if (tree[rt].mid < rs) update(rt << 1 | 1, lr, rs, val);
    return;
}
bool query(int rt, int pos) {
    if (tree[rt].lr > pos || tree[rt].rs < pos) return false;
    if (tree[rt].lr == tree[rt].rs) return tree[rt].tag == 0;
    pushDown(rt);
    if (tree[rt].mid >= pos) return query(rt << 1, pos);
    return query(rt << 1 | 1, pos);
}

ll query1(int rt, int pos) {
    if (tree[rt].lr > pos || tree[rt].rs < pos) return -1;
    if (tree[rt].lr == tree[rt].rs) return tree[rt].tag;
    pushDown(rt);
    if (tree[rt].mid >= pos) return query(rt << 1, pos);
    return query(rt << 1 | 1, pos);
}
bool check(int x) {
    if (x == 2) return true;
    if (x % 2 == 0) return false;
    for (int i = 3; i * i <= x; i += 2) {
        if (x % i == 0) return false;
    }
    return true;
}
int cnt = 0;
void init() {
    for (int i = 2; i <= 100; ++i) {
        if (!check(i)) continue;
        mp[i] = cnt++;
        pri.push_back(i);
    }
}
vector<vector<int>>graph(N);
int a[N];
int father[N], depth[N], siz[N], son[N];
void dfs1(int u, int f) {
    father[u] = f; depth[u] = depth[f] + 1;
    siz[u] = 1;
    int maxsize = -1;
    for (auto g : graph[u]) {
        if (g == f) continue;
        dfs1(g, u);
        siz[u] += siz[g];
        if (siz[g] > maxsize) maxsize = siz[g], son[u] = g;
    }
    return;
}
int tim, dfn[N], top[N], outtime[N];
void dfs2(int u, int t) {
    dfn[u] = ++tim;
    top[u] = t;
    if (!son[u]) return;
    dfs2(son[u], t);
    for (auto g : graph[u]) {
        if (g == father[u] || g == son[u]) continue;
        dfs2(g, g);
    }
    outtime[u] = tim;
    return;
}
void updateChain(int u, int v, ll val) {
    while (top[u] != top[v]) {
        if (depth[top[u]] < depth[top[v]]) swap(u, v);
        update(1, dfn[top[u]], dfn[u], val);
        u = father[top[u]];
    }
    if (depth[u] > depth[v]) swap(u, v);
    update(1, dfn[u], dfn[v], val);
    return;
}
int f[N][20], dep[N];
void dfs(int u, int fa) {
    f[u][0] = fa;
    dep[u] = dep[fa] + 1;
    for (int i = 1; (1 << i) <= dep[u]; ++i) f[u][i] = f[f[u][i - 1]][i - 1];
    for (auto v : graph[u]) {
        if (v == fa) continue;
        dfs(v, u);
    }
    return;
}
int LCA(int u, int v) {
    if (dep[u] > dep[v]) swap(u, v);
    for (int i = 18; ~i; --i)
        if (dep[f[v][i]] >= dep[u]) v = f[v][i];
    if (u == v) return u;
    for (int i = 18; ~i; --i) {
        if (f[u][i] != f[v][i]) {
            u = f[u][i];
            v = f[v][i];
        }
    }
    return f[u][0];
}
void solve() {
    init();
    int n, m, q;
    cin >> n;
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }
    dfs(1, 1);
    dfs1(1, 1);
    dfs2(1, 1);
    buildTree(1, 1, n);
    cin >> m;
    auto cal = [&](int w) {
        ll res = 0;
        for (auto p : pri) {
            if (w % p != 0) continue;
            int cnt = 0;
            while (w % p == 0) cnt++, w /= p;
            if (cnt % 2) res |= (1ll << mp[p]);
            if (w == 1) break;
        }
        return res;
    };
    for (int i = 1; i <= m; ++i) {
        int a, b, w;
        cin >> a >> b >> w;
        ll val = cal(w);
        int p = LCA(a, b);
        updateChain(a, b, val);
        updateChain(1, p, val);
        updateChain(p, p, val);
    }
    cin >> q;
    while (q--) {
        int x;
        cin >> x;
        if (query(1, dfn[x])) cout << "YES" << '\n';
        else cout << "NO" << '\n';
    }
    //for (int i = 1; i <= n; ++i) cout << query1(1, dfn[i]) << " ";
    return;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T = 1;
    //cin >> T;
    while (T--) solve();
    return 0;
}

标签:rt,Square,return,rs,int,tree,Tree,leq
来源: https://www.cnblogs.com/cherish-/p/16538416.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有