• 在线更新问题 HDU5877 线段树


    题目大意:给你一棵树,有n-1条边,每条边都有方向,每个顶点有权值,给出weak pair的定义是val[u]*val[v] <=k,u是v的祖先,问有多少对这样的顶点

    思路:创建线段树,通过dfs动态创建,每次都不断更新。因为我们只能是根节点开始往下的,所以我们遍历到兄弟节点的之前要把其他的兄弟节点的信息给删除掉。(这就和用vis标记一样的,一会儿变为true,一会儿变为false)

    不过我很奇怪,为啥我的代码没有吧k/a[i]放进去就迷之RE了

    当然,这道题也可以用主席树做,也可以用treap做

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    const int maxn = 4e5 + 5;
    LL a[maxn], b[maxn], d[maxn], tree[maxn * 4];
    LL n, m, k, lenb, ans;
    vector<int> E[maxn];
    
    int query(int o, int l, int r, int ql, int qr){
        if (l >= ql && r <= qr){
            return tree[o];
        }
        int cnt = 0;
        int mid = (l + r) / 2;
        if (ql <= mid) cnt += query(o << 1, l, mid, ql, qr);
        if (qr > mid) cnt += query(o << 1 | 1, mid + 1, r, ql, qr);
        return cnt;
    }
    
    inline void push_up(int o){
        int lb = o << 1, rb = o << 1 | 1;
        tree[o] = tree[lb] + tree[rb];
    }
    
    void update (int o, int l, int r, int pos, int val){
        if (l == r && l == pos) {
            tree[o] += val;
            return ;
        }
        int mid = (l + r) / 2;
        if (pos <= mid) update(o << 1, l, mid, pos, val);
        if (pos > mid) update(o << 1 | 1, mid + 1, r, pos, val);
        push_up(o);
    }
    
    void dfs(int u){
        int pos = lower_bound(b + 1, b + 1 + m, a[u]) - b;
        int posk = lower_bound(b + 1, b + 1 + m, k / a[u]) - b;
        ans += query(1, 1, lenb, 1, posk);
        int len = E[u].size();
        update(1, 1, lenb, pos, 1);
        for (int i = 0; i < len; i++){
            int v = E[u][i];
            dfs(v);
        }
        update(1, 1, lenb, pos, -1);
    }
    
    int main(){
        int t; cin >> t;
        while (t--){
            memset(d, 0, sizeof(d));
            memset(tree, 0, sizeof(tree));
            scanf("%I64d%I64d", &n, &k);
            for (int i = 1; i <= n; i++){
                scanf("%I64d", a + i);
                b[i] = a[i];
                E[i].clear();
            }
            m = n;
            for (int i = 1; i <= n; i++) b[++m] = k / a[i];
            
            sort(b + 1, b + 1 + m);
            lenb = unique(b + 1, b + 1 + m) - b - 1;///序列长度1~n
            ///printf("lenb = %d
    ", lenb);
            for (int i = 1; i <= n - 1; i++){
                int u, v; scanf("%d%d", &u, &v);
                E[u].pb(v);
                d[v]++;
            }
            ans = 0;
            for (int i = 1; i <= n; i++){
                if (d[i] == 0){
                    dfs(i);
                    break;
                }
            }
            printf("%I64d
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    20201029-1 每周例行报告
    20201022-1 每周例行报告
    20201015-3 每周例行报告
    作业要求 20201008-1 每周例行报告
    《机器学习》第二次作业——第四章学习记录和心得
    实验 7:OpenDaylight 实验——Python 中的 REST API 调用
    实验 6:OpenDaylight 实验——OpenDaylight 及 Postman 实现流表下发
    实验 5:OpenFlow 协议分析和 OpenDaylight 安装
    实验 4:Open vSwitch 实验——Mininet 中使用 OVS 命令
    实验 3:Mininet 实验——测量路径的损耗率
  • 原文地址:https://www.cnblogs.com/heimao5027/p/5863152.html
Copyright © 2020-2023  润新知