• P3605 [USACO17JAN]Promotion Counting P


    P3605 USACO17JAN Promotion Counting P
    线段树合并板子。
    考虑儿子对父亲的贡献,直接把线段树合并上去就好了。
    然后直接询问 (val gt p_n) 的就好了。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    
    using namespace std;
    
    typedef long long ll;
    const ll MAXN = 3e6+10;
    
    struct edge {
        ll l, r, val;
    } t[MAXN << 1];
    
    ll N, M, val[MAXN << 1], rt[MAXN << 1], tot, ans[MAXN << 1];
    vector <ll> g[MAXN], q;
    
    ll ask(ll, ll, ll, ll);
    ll build(ll, ll, ll, ll);
    ll clon(ll);
    void dfs(ll, ll);
    ll merg(ll, ll);
    void updata(ll);
    
    int main() {
        scanf("%lld", &N);
        for (ll i = 1; i <= N; i++) {scanf("%lld", val+i);q.push_back(val[i]);}
        for (ll ff, i = 2; i <= N; i++) {
            scanf("%lld", &ff);
            g[ff].push_back(i);
        }
        sort(q.begin(), q.end());
        q.erase(unique(q.begin(), q.end()), q.end());
        for (ll i = 1; i <= N; i++) val[i] = lower_bound(q.begin(), q.end(), val[i]) - q.begin() + 1;
        for (ll i = 1; i <= N; i++) rt[i] = build(rt[i], 1, N, val[i]);
        dfs(1, 0);
        for (ll i = 1; i <= N; i++) printf("%lld
    ", ans[i]);
        return 0;
    }
    
    void dfs(ll n, ll ff) {
        for (unsigned int i = 0; i < g[n].size(); i++) {
            ll v = g[n][i];
            if (v == ff) continue;
            else {
                dfs(v, n);
                rt[n] = merg(rt[n], rt[v]);
            }
        }
        ans[n] = ask(rt[n], 1, N, val[n]);
    }
    
    ll ask(ll node, ll l, ll r, ll va) {
        if (va < l) return t[node].val;
        if (r <= va) return 0;
        ll mid = (l + r) >> 1, ret = 0;
        if (va <= mid) {
        	if (t[node].l) ret += ask(t[node].l, l, mid, va);
    		if (t[node].r) ret += ask(t[node].r, mid+1, r, va);
        } else {
        	if (t[node].r) ret = ask(t[node].r, mid+1, r, va);	
        }
        return ret;
    }
    
    ll merg(ll node, ll lst) {
        if (!node || !lst) return node + lst;
        t[node].val += t[lst].val;
        t[node].l = merg(t[node].l, t[lst].l);
        t[node].r = merg(t[node].r, t[lst].r);
        updata(node);
        return node;
    }
    
    ll build(ll node, ll l, ll r, ll pos) {
        node = clon(node);
        if (l == r) {
            t[node].val++;
            return node;
        }
        ll mid = (l + r) >> 1;
        if (pos <= mid) t[node].l = build(t[node].l, l, mid, pos);
        else t[node].r = build(t[node].r, mid+1, r, pos);
        updata(node);
        return node;
    }
    
    void updata(ll node) {
    	t[node].val = 0;
    	if (t[node].l) t[node].val += t[t[node].l].val;
    	if (t[node].r) t[node].val += t[t[node].r].val;
    }
    
    ll clon(ll node) {
        t[++tot] = t[node];
        return tot;
    }
    
    Yukkuri si te yi te ne
  • 相关阅读:
    从C,C++,JAVA和C#看String库的发展(一)----C语言和C++篇
    Intent----android中的伟大邮差
    一步一步掌握线程机制(五)---等待与通知机制
    一步一步掌握线程机制(四)---同步方法和同步块
    一步一步掌握线程机制(三)---synchronized和volatile的使用
    利用单例模式解决全局访问问题
    一步一步掌握java的线程机制(二)----Thread的生命周期
    一步一步掌握java的线程机制(一)----创建线程
    如何快速学会android的四大基础----Service篇
    前端工程师必备实用网站
  • 原文地址:https://www.cnblogs.com/Gensokyo-Alice/p/13681351.html
Copyright © 2020-2023  润新知