BZOJ 4756 Promotion Counting(线段树合并 || dfs)
来源:互联网 发布:阿里云邮箱app 编辑:程序博客网 时间:2024/06/05 03:12
题意:给你一棵n个节点的树,根为1,问你每个节点,它的子树中有几个节点比它大。
思路:
有一个简单的方法是可以遍历一下这棵树,树状数组维护,对于每个点的答案为 子树节点个数-(遍历它后比它小的数的个数-遍历它前比它小的数的个数)。遍历完它的子树节点后把它插入树状数组。
还有一个方法是对于每个节点建立一颗权值线段树,然后自底向上合并,每次合并后就可以直接查找比它大的数的个数,因为此时的树中只有它子树的节点。
线段树合并代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 1e5+5;const int maxnode = 2e6+5;int tree[maxnode], lch[maxnode], rch[maxnode];int a[maxn], b[maxn], head[maxn], root[maxn], ans[maxn];int n, k, sz, seg;struct node{ int v, next;}edge[maxn];void init(){ k = 0, sz = 1, seg = 0; memset(head, -1, sizeof(head)); memset(tree, 0, sizeof(tree)); memset(root, 0, sizeof(root)); memset(rch, 0, sizeof(rch)); memset(lch, 0, sizeof(lch));}void addEdge(int u, int v){ edge[k].v = v; edge[k].next = head[u]; head[u] = k++;}void pushup(int rt){ tree[rt] = tree[lch[rt]]+tree[rch[rt]];}void build(int &rt, int l, int r, int pos){ rt = ++seg; if(l == r) { tree[rt] = 1; return ; } int mid = (l+r)/2; if(pos <= mid) build(lch[rt], l, mid, pos); else build(rch[rt], mid+1, r, pos); pushup(rt);}int query(int rt, int l, int r, int i, int j){ if(i <= l && j >= r) return tree[rt]; int mid = (l+r)/2; int res = 0; if(i <= mid) res += query(lch[rt], l, mid, i, j); if(j > mid) res += query(rch[rt], mid+1, r, i, j); return res;}int merge(int x, int y){ if(!x) return y; if(!y) return x; lch[x] = merge(lch[x], lch[y]); rch[x] = merge(rch[x], rch[y]); pushup(x); return x;}void dfs(int u){ for(int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].v; dfs(v); root[u] = merge(root[u], root[v]); } ans[u] = query(root[u], 1, n, a[u]+1, n);}int main(void){ while(cin >> n) { init(); for(int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i]; sort(b+1, b+1+n); int t = unique(b+1, b+1+n)-b-1; for(int i = 1; i <= n; i++) a[i] = lower_bound(b+1, b+1+t, a[i])-b; for(int i = 2; i <= n; i++) { int x; scanf("%d", &x); addEdge(x, i); } for(int i = 1; i <= n; i++) build(root[i], 1, n, a[i]); dfs(1); for(int i = 1; i <= n; i++) printf("%d\n", ans[i]); } return 0;}
dfs代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 1e5+5;const int maxm = 5e5+5;int ans[maxn], num[maxn], head[maxm], tree[maxn];int n, k, a[maxn], b[maxn];struct node{ int v, next;}edge[maxm];void init(){ k = 0; memset(head, -1, sizeof(head)); memset(num, 0, sizeof(num)); memset(tree, 0, sizeof(tree));}void addEdge(int u, int v){ edge[k].v = v; edge[k].next = head[u]; head[u] = k++;}int lowbit(int x){ return x&(-x);}void update(int pos, int val){ while(pos < maxn) { tree[pos] += val; pos += lowbit(pos); }}int query(int pos){ int res = 0; while(pos) { res += tree[pos]; pos -= lowbit(pos); } return res;}void dfs(int u){ int pre = query(a[u]); num[u] = 1; for(int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].v; dfs(v); num[u] += num[v]; } int cur = query(a[u]); ans[u] = num[u]-(cur-pre)-1; update(a[u], 1);}int main(void){ while(cin >> n) { init(); for(int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i]; sort(b+1, b+1+n); int t = unique(b+1, b+1+n)-b-1; for(int i = 1; i <= n; i++) a[i] = lower_bound(b+1, b+1+t, a[i])-b; for(int i = 2; i <= n; i++) { int x; scanf("%d", &x); addEdge(x, i); } dfs(1); for(int i = 1; i <= n; i++) printf("%d\n", ans[i]); } return 0;}
阅读全文
1 0
- BZOJ 4756 Promotion Counting(线段树合并 || dfs)
- bzoj 4756: [Usaco2017 Jan]Promotion Counting (线段树合并)
- 【bzoj 4756】Promotion Counting(线段树合并)
- BZOJ 4756 [Usaco2017 Jan]Promotion Counting 线段树合并
- BZOJ[4756][Usaco2017 Jan]Promotion Counting 线段树合并
- BZOJ 4756 [Usaco2017 Jan]Promotion Counting dfs序+主席树
- 4756: [Usaco2017 Jan]Promotion Counting 线段树合并
- bzoj 4756: [Usaco2017 Jan]Promotion Counting
- bzoj 4530(DFS序+线段树合并)
- bzoj 4756(线段树合并)
- 4756: [Usaco2017 Jan]Promotion Counting
- 线段树学习(2)POI Promotion
- bzoj 4551(DFS序+线段树)
- bzoj 2212(线段树合并)
- bzoj 4756: [Usaco2017 Jan]Promotion Counting dsu on tree+树状数组
- 洛谷 P3605 [USACO17JAN]Promotion Counting晋升者计数——树状数组,权值线段树
- BZOJ 3123 线段树合并
- USACO2017JanuaryPlatinum Promotion Counting(奶牛升职计数)
- 《大话数据结构》学习笔记--chapter 6
- 关于Spring MVC中的表单标签库的使用
- Codeforces Round #401 (Div. 2) D. Cloud of Hashtags【模拟、贪心】
- hibernate_2
- 8.10-8.11训练总结
- BZOJ 4756 Promotion Counting(线段树合并 || dfs)
- 给自己一次警告——NSNotification
- Camtasia 9全套视频入门到精通
- 图论--网络流初步(最大流,增广路)
- 如何用svn新建属于自己的分支
- mysql 常用命令技巧大全
- 源码编译形式安装mysql
- 设计模式之策略模式--慕课网笔记
- 魔力手环--网易2017春招实习笔试编程题