bzoj4756 [Usaco2017 Jan]Promotion Counting

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4756

【题解】

dsu on tree,树状数组直接上

O(nlog^2n)

# include <vector>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 2e5 + 10, N = 4e5 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, a[M]; 
vector<int> ps;
int ans[M];

int head[M], nxt[M], to[M], tot=0;
inline void add(int u, int v) {
    ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
}

# define lb(x) (x&(-x))
struct BIT {
    int c[N];
    inline void edt(int x, int d) {
        for (; x<=n; x+=lb(x)) c[x] += d;
    }
    inline int sum(int x) {
        int ret = 0;
        for (; x; x-=lb(x)) ret += c[x];
        return ret;
    }
    inline int sum(int x, int y) {
        if(x>y) return 0;
        return sum(y) - sum(x-1);
    }
}T;
# undef lb

int sz[M];
inline void dfssize(int x) {
    sz[x] = 1;
    for (int i=head[x]; i; i=nxt[i]) {
        dfssize(to[i]);
        sz[x] += sz[to[i]];
    }
}

bool big[M];
inline void dfsans(int x) {
    T.edt(a[x], 1);
    for (int i=head[x]; i; i=nxt[i]) 
        if(!big[to[i]]) dfsans(to[i]);
}

inline void delans(int x) {
    T.edt(a[x], -1);
    for (int i=head[x]; i; i=nxt[i])
        if(!big[to[i]]) delans(to[i]);
}

inline void dsu(int x, bool iskep) {
    int mx = -1, bigc = -1;
    for (int i=head[x]; i; i=nxt[i]) 
        if(sz[to[i]] > mx) mx = sz[to[i]], bigc = to[i];
    for (int i=head[x]; i; i=nxt[i]) 
        if(to[i] != bigc) dsu(to[i], 0);
    if(bigc != -1) big[bigc] = 1, dsu(bigc, 1);
    dfsans(x);
    ans[x] = T.sum(a[x]+1, n);
    if(bigc != -1) big[bigc] = 0;
    if(!iskep) delans(x);            
}
        

int main() {
    cin >> n;
    for (int i=1; i<=n; ++i) {
        scanf("%d", &a[i]);
        ps.push_back(a[i]);
    }
    
    sort(ps.begin(), ps.end());
    ps.erase(unique(ps.begin(), ps.end()), ps.end());
    
    for (int i=1; i<=n; ++i) a[i] = lower_bound(ps.begin(), ps.end(), a[i]) - ps.begin() + 1;

    
    for (int i=2, fa; i<=n; ++i) {
        scanf("%d", &fa);
        add(fa, i);
    }
    
    dfssize(1);
    dsu(1, 1);
    
    for (int i=1; i<=n; ++i) printf("%d\n", ans[i]);
    
    return 0;
}
View Code

 

posted @ 2017-05-26 16:17  Galaxies  阅读(233)  评论(0编辑  收藏  举报