zoukankan      html  css  js  c++  java
  • P3605 [USACO17JAN]Promotion Counting晋升者计数

    题目:传送门

    ps:方法较多,主席树,树状数组,线段树合并(感觉统计子树的某些信息很好用)

    线段树合并:对每个节点建一颗线段树(实际上是一条长度为lg(n)的链),然后自底向上合并。

    inline void upd(int &x, int y) { x > y && (x = y); }
    
    const int N = 100005;
    
    int n, tot, cnt;
    int sum[20 * N], ls[20 * N], rs[20 * N], root[N], head[N], a[N], ans[N];
    
    struct node { int to, next; } e[2 * N];
    
    vector<int> id;
    
    inline int getId(int x) { return lower_bound(Range(id), x) - id.begin(); }
    
    void Inite() {
        cnt = tot = 0;
        mem(head, -1);
    }
    
    void addedge(int u, int v) {
        e[tot].to = v, e[tot].next = head[u], head[u] = tot++;
    }
    
    void Pushup(int rt) {
        sum[rt] = sum[ls[rt]] + sum[rs[rt]];
    }
    
    void Build(int l, int r, int &rt, int pos) {
        if (!rt) rt = ++cnt;
        if (l == r) {
            sum[rt]++;
            return;
        }
        int mid = (l + r) >> 1;
        if (pos <= mid) Build(l, mid, ls[rt], pos);
        else Build(mid + 1, r, rs[rt], pos);
        Pushup(rt);
    }
    
    int Merge(int x, int y) {
        if (!x || !y) return x ^ y;
        ls[x] = Merge(ls[x], ls[y]);
        rs[x] = Merge(rs[x], rs[y]);
        Pushup(x);
        return x;
    }
    
    int Query(int l, int r, int rt, int L, int R) {
        if (l > R || r < L || L > R) return 0;
        if (L <= l && r <= R) return sum[rt];
        int ans = 0;
        int mid = (l + r) >> 1;
        ans += Query(l, mid, ls[rt], L, R);
        ans += Query(mid + 1, r, rs[rt], L, R);
        return ans;
    }
    
    void DFS(int u) {
        for (int i = head[u]; ~i; i = e[i].next) {
            DFS(e[i].to);
            root[u] = Merge(root[u], root[e[i].to]);
        }
        ans[u] = Query(1, n, root[u], getId(a[u]) + 2, n);
    }
    
    
    int main()
    {
        sc(n);
        Rep(i, 1, n) sc(a[i]), id.pb(a[i]);
    
        sort(Range(id));
        Rep(i, 1, n) Build(1, n, root[i], getId(a[i]) + 1);
    
        Inite();
        rep(i, 1, n) {
            int x;
            sc(x);
            addedge(x, i + 1);
        }
    
        DFS(1);
        Rep(i, 1, n) pr(ans[i]);
        return 0;
    }
    View Code

    树状数组:借助差分的思想,答案 = 搜索完u的子树时比节点u权值大的节点 - 未搜索u的子树时比节点u权值大的节点。

    const int N = 100005;
    
    int n, cnt;
    int a[N], bit[N], ans[N];
    
    vector<int> id, G[N];
    
    int getId(int x) { return lower_bound(Range(id), x) - id.begin(); }
    
    int lowbit(int x) { return x & -x; }
    
    void add(int pos) {
        for (int i = pos; i <= n; i += lowbit(i)) bit[i]++;
    }
    
    int sum(int pos) {
        int res = 0;
        for (int i = pos; i; i -= lowbit(i)) res += bit[i];
        return res;
    }
    
    void DFS(int u) {
        cnt++;
        add(getId(a[u]) + 1);
        int tp = cnt - sum(getId(a[u]) + 1);
        for (auto v : G[u]) DFS(v);
        ans[u] = cnt - sum(getId(a[u]) + 1) - tp;
    }
    
    
    int main()
    {
        sc(n);
        Rep(i, 1, n) sc(a[i]), id.pb(a[i]);
    
        sort(Range(id));
    
        rep(i, 1, n) {
            int x;
            sc(x);
            G[x].pb(i + 1);
        }
    
        cnt = 0;
        DFS(1);
    
        Rep(i, 1, n) pr(ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    Notepad++ 使用nppexec插件配置简易开发环境
    Notepad++一键编译运行(Python、Java、C++)
    Java翁恺(1)——下载安装
    stm32正点原子学习笔记(30)窗口看门狗
    小程序模板
    Wireshark使用介绍(二):应用Wireshark观察基本网络协议
    Wireshark使用介绍(一):Wireshark基本用法
    Git 教程(四):标签和其他
    Git 教程(三):仓库与分支
    Git 教程(二):提交和回退
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/9553533.html
Copyright © 2011-2022 走看看