树状数组 P3605 [USACO17JAN]Promotion Counting晋升者计数
P3605 [USACO17JAN]Promotion Counting晋升者计数
题目描述
奶牛们又一次试图创建一家创业公司,还是没有从过去的经验中吸取教训--牛是可怕的管理者!
为了方便,把奶牛从 1 \(\cdots\) N(1 \(\leq\) N \(\leq\) 100, 000) 编号,把公司组织成一棵树,1 号奶牛作为总裁(这棵树的根节点)。除了总裁以外的每头奶牛都有一个单独的上司(它在树上的 “双亲结点”)。所有的第 i 头牛都有一个不同的能力指数 p(i),描述了她对其工作的擅长程度。如果奶牛 i 是奶牛 j 的祖先节点(例如,上司的上司的上司),那么我们我们把奶牛 j 叫做 i 的下属。
不幸地是,奶牛们发现经常发生一个上司比她的一些下属能力低的情况,在这种情况下,上司应当考虑晋升她的一些下属。你的任务是帮助奶牛弄清楚这是什么时候发生的。简而言之,对于公司的中的每一头奶牛 i,请计算其下属 j 的数量满足 p(j) > p(i)。
输入输出格式
输入格式:输入的第一行包括一个整数 N。
接下来的 N行包括奶牛们的能力指数 p(1)⋯p(N). 保证所有数互不相同,在区间 1⋯109 之间。
接下来的 N−1 行描述了奶牛2⋯N 的上司(双亲节点)的编号。再次提醒,1 号奶牛作为总裁,没有上司。
输出格式:输出包括 N 行。输出的第 i 行应当给出有多少奶牛 i 的下属比奶牛i能力高。
一句话题意:给出一个树形结构,求每个节点其子树中节点权值比他大的个数。
如果树退化成链的话,那就是裸的求逆序对数,上树状数组。
接下来考虑树的情况,因为要求该节点与其子树中节点的大小关系,所以不难想到搞出一个DFS序,然后将DFS序看成序列,对上面的点每一次进行区间求和即可。
考虑我们现在要求节点i的答案,那么在树状数组里的一定是比i要大的,既然知道了这个顺序,那么就将每个节点按权值大小排序,每一次查询在DFS序里该点的dfn到dfn+size-1即可查询整个区间,用右端点减去左端点减一的位置的答案,即可得出此时的答案,再将现在这个点放进树状数组里,表示个数加一,去接着为权值更小的点的答案做贡献。
code:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int wx=100017; inline int read(){ int sum=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar(); } return sum*f; } struct e{ int nxt,to; }edge[wx*2]; struct node{ int v,id; friend bool operator < (const node& a,const node& b){ return a.v>b.v; } }a[wx]; int head[wx],size[wx],dfn[wx],ans[wx],sum[wx]; int n,num,tot,x; void add(int from,int to){ edge[++num].nxt=head[from]; edge[num].to=to; head[from]=num; } void dfs(int u){ dfn[u]=++tot;size[u]=1; for(int i=head[u];i;i=edge[i].nxt){ int v=edge[i].to; dfs(v); size[u]+=size[v]; } } void update(int pos,long long k) { for(int i=pos;i<=n;i+=(i&-i)){ sum[i]+=k; } } int query(int x){ long long re=0; for(int i=x;i>=1;i-=(i&-i)){ re+=sum[i]; } return re; } int main(){ n=read(); for(int i=1;i<=n;i++)a[i].v=read(),a[i].id=i; for(int i=2;i<=n;i++){ x=read();add(x,i); } dfs(1); sort(a+1,a+1+n); for(int i=1;i<=n;i++){ ans[a[i].id]=query(dfn[a[i].id]+size[a[i].id]-1)-query(dfn[a[i].id]-1); update(dfn[a[i].id],1); } for(int i=1;i<=n;i++)printf("%d\n",ans[i]); return 0; }
- [luoguP3608] [USACO17JAN]Balanced Photo平衡的照片(树状数组 + 离散化)
- [bzoj2058][Usaco2010 Nov]Cow Photographs_树状数组_动态规划
- 【动态规划】【树状数组】[USACO2011 FEB]奶牛抗议
- 【USACO 2012 Open】Running Laps(树状数组)
- 洛谷 P3605 [USACO17JAN]Promotion Counting晋升者计数——树状数组,权值线段树
- Binary Indexed Tree树状数组初步 & USACO2011 November Gold Above the Median
- 树状数组【bzoj1782】: [Usaco2010 Feb]slowdown 慢慢游
- USACO5.3 IDDFS_强连通_二维树状数组_斐蜀定理_矩形切割
- bzoj 4411 USACO16FEB 负载平衡Load Balancing(扫描线,树状数组,三分答案,前缀和)
- USACO-Section 3.3 Home on the Range (树状数组||DP)
- 树状数组(转载修改添加)
- HDU 2642 Stars 简单二维树状数组应用
- 历届试题 小朋友排队(树状数组求逆序数)
- 【HDU 3333】【离线询问 树状数组 前驱思想】Turing Tree【 求区间中不同的数的和】
- PKU 1195 二维树状数组
- hdu 4217 Data Structure?(树状数组)
- 【序列莫队+二分答案+树状数组】POJ2104-K-th Number
- 树状数组: fzu oj 2236 第十四个目标
- POJ 2182 Lost Cows (树状数组,递推)
- lightoj-1080-Binary Simulation【树状数组】