zoukankan      html  css  js  c++  java
  • 在线更新问题 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
  • 相关阅读:
    性能测试工具LoadRunner19-LR之Controller IP欺骗
    JavaScript—06数组与函数
    JavaScript—05流程控制与代码规范要求
    JavaScript—04运算符
    JS做简单的留言板
    JavaScript—03 变量与数据类型
    JavaScript—02 JS组成及注释等
    JavaScript—01汇编语言和计算机基础脑图
    01移动端布局基础-脑图
    解决粘包-复杂版
  • 原文地址:https://www.cnblogs.com/heimao5027/p/5863152.html
Copyright © 2011-2022 走看看