本题为权值树状数组模板题。
题目链接:https://www.luogu.com.cn/problem/P3605
首先,这道题的能力值数据规模较大,于是我们先离散化。
接着,我们发现这道题题意类似于找逆序对数量,只是换成了在树上,要统计各店子树上权值大于该点的点数。统计相对大小的对数,显然提示我们使用权值树状数组。问题是怎么统计子树上权值满足?我们可以先记录已插入数据中满足以上等式的点数,接着将u的后代后代全部插入,再统计一遍,两者的差值即为所求。
代码实现:
#include<bits/stdc++.h>
using namespace std;
int const N=1e5+10;
struct edge{
int u,v,nxt;
}e[N];
int t[N],n,a[N],b[N],cnt,first[N];
inline int lowbit(int x){
return x&(-x);
}
struct node{
int id,ans;
}d[N];
inline void insert(int lac,int val){
for(int i=lac;i<=n;i+=lowbit(i)){
t[i]+=val;
}
}
inline int query(int lac){
int res=0;
for(int i=lac;i>0;i-=lowbit(i)){
res+=t[i];
}
return res;
}
inline void dfs(int u){
insert(a[u],1);//cout<<u<<endl;
int tmp=query(n)-query(a[u]);
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
dfs(v);
}
d[u].ans=query(n)-query(a[u])-tmp;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
b[i]=a[i];
}
sort(b+1,b+n+1);
for(int i=1;i<=n;i++){
a[i]=lower_bound(b+1,b+n+1,a[i])-b;
//cout<<a[i]<<" ";
}
for(int i=1;i<n;i++){
int v=i+1,u;cin>>u;
e[++cnt].u=u;e[cnt].v=v;
e[cnt].nxt=first[u];
first[u]=cnt;
}
dfs(1);
for(int i=1;i<=n;i++){
cout<<d[i].ans<<"\n";
}
return 0;
}
199

被折叠的 条评论
为什么被折叠?



