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\n", 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;
}
posted @ 2020-09-16 20:52  Gensokyo_Alice  阅读(145)  评论(0编辑  收藏  举报