BZOJ 4756 「USACO 2017 · January」Promotion Counting 发表于 2019.07.14 | 分类于 题解 | 14 屑题,一眼秒。 听说可以离散化然后树状数组容斥掉兄弟的贡献? 如果把 DFS 序搞出来,就是一个二维偏序了。 但是我还是喜欢写线段树合并! 多优美啊! 代码: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566#include <cstdio>using namespace std;const int N = 1e5;const int C = 1e9;int n,a[N + 5];int to[N + 5],pre[N + 5],first[N + 5];inline void add(int u,int v){ static int tot = 0; to[++tot] = v,pre[tot] = first[u],first[u] = tot;}struct node{ int sum; int ls,rs;} seg[(N << 6) + 10];int rt[N + 5];void insert(int x,int &p,int tl,int tr){ static int tot = 0; if(!p) p = ++tot; ++seg[p].sum; if(tl == tr) return ; int mid = tl + tr >> 1; x <= mid ? insert(x,seg[p].ls,tl,mid) : insert(x,seg[p].rs,mid + 1,tr);}int query(int l,int r,int p,int tl,int tr){ if(!p || (l <= tl && tr <= r)) return seg[p].sum; int ret = 0; int mid = tl + tr >> 1; l <= mid && (ret += query(l,r,seg[p].ls,tl,mid)); r > mid && (ret += query(l,r,seg[p].rs,mid + 1,tr)); return ret;}int merge(int x,int y){ if(!x || !y) return x | y; seg[x].sum += seg[y].sum; seg[x].ls = merge(seg[x].ls,seg[y].ls),seg[x].rs = merge(seg[x].rs,seg[y].rs); return x;}int ans[N + 5];void dfs(int p,int fa){ for(register int i = first[p];i;i = pre[i]) if(to[i] ^ fa) dfs(to[i],p),rt[p] = merge(rt[p],rt[to[i]]); ans[p] = query(a[p] + 1,C,rt[p],1,C),insert(a[p],rt[p],1,C);}int main(){ scanf("%d",&n); for(register int i = 1;i <= n;++i) scanf("%d",a + i); int u; for(register int i = 2;i <= n;++i) scanf("%d",&u),add(u,i); dfs(1,0); for(register int i = 1;i <= n;++i) printf("%d\n",ans[i]);} 本文作者: Alpha1022 本文链接: https://www.alpha1022.me/articles/bzoj-4756.htm 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明出处!