bzoj4756
Posted 123456
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4756相关的知识,希望对你有一定的参考价值。
http://www.lydsy.com/JudgeOnline/problem.php?id=4756
水题一枚。。。但是我写了一个小时。。。手贱打反查不出来。。。
就是每次线段树合并,先把自己的儿子都合并了, 最后和自己合并。。。
#include<bits/stdc++.h> using namespace std; const int N = 100010; vector<int> G[N]; int n, sum, cnt; int t[N], id[N], size[N * 20], lc[N * 20], rc[N * 20], ans[N], root[N * 20]; bool cp(int i, int j) { return t[i] < t[j]; } void update(int l, int r, int &x, int pos) { x = ++cnt; int mid = (l + r) >> 1; ++size[x]; if(l == r) return; if(pos <= mid) update(l, mid, lc[x], pos); else update(mid + 1, r, rc[x], pos); } int merge(int x, int y) { if(!x || !y) return x + y; sum += size[lc[x]] * size[rc[y]]; lc[x] = merge(lc[x], lc[y]); rc[x] = merge(rc[x], rc[y]); size[x] = size[lc[x]] + size[rc[x]]; return x; } void dfs(int u) { int last = 0; for(int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; dfs(v); root[v] = merge(root[v], root[last]); last = v; } sum = 0; root[u] = merge(root[u], root[last]); ans[u] = sum; } int main() { scanf("%d", &n); for(int i = 1; i <= n; ++i) { scanf("%d", &t[i]); id[i] = i; } sort(id + 1, id + n + 1, cp); for(int i = 1; i <= n; ++i) t[id[i]] = t[id[i - 1]] + (t[id[i]] != t[id[i - 1]]); for(int i = 1; i <= n; ++i) update(1, n, root[i], t[i]); for(int i = 2; i <= n; ++i) { int x; scanf("%d", &x); G[x].push_back(i); } dfs(1); for(int i = 1; i <= n; ++i) printf("%d\n", ans[i]); return 0; }
以上是关于bzoj4756的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ4756][Usaco2017 Jan]Promotion Counting 树状数组
[BZOJ] 4756: [Usaco2017 Jan]Promotion Counting #线段树合并
bzoj4756[Usaco2017 Jan]Promotion Counting 离散化+树状数组