題目描述:
無。
題目分析:
就是求一個節點子樹裏有多少個節點編號比這個數小,直接權值線段樹動態開點線段樹合併就好了。
題目鏈接:
AC代碼:
#include <iostream>
#include <cstdio>
const int maxm=110000;
int ans[maxm],root[maxm];
int head[maxm],net[maxm*2],to[maxm*2];
int cnt,n,m;
inline void addedge(int u,int v){to[++cnt]=v,net[cnt]=head[u],head[u]=cnt;}
struct seg{
int ls[maxm*40],rs[maxm*40];
int sum[maxm*40];
int sz;
void insert(int &now,int l,int r,int ind)
{
if(!now) now=++sz;
if(l>=r)
{
sum[now]=1;
return;
}
int mid=(l+r)>>1;
ind<=mid?insert(ls[now],l,mid,ind):insert(rs[now],mid+1,r,ind);
sum[now]=sum[ls[now]]+sum[rs[now]];
}
int merge(int x,int y)
{
if(!x||!y) return x+y;
ls[x]=merge(ls[x],ls[y]);
rs[x]=merge(rs[x],rs[y]);
sum[x]=sum[ls[x]]+sum[rs[x]];
return x;
}
int ask(int now,int l,int r,int ql,int qr)
{
if(!now) return 0;
if(ql<=l&&r<=qr) return sum[now];
int mid=(l+r)>>1;
int res=0;
if(ql<=mid) res+=ask(ls[now],l,mid,ql,qr);
if(qr>mid) res+=ask(rs[now],mid+1,r,ql,qr);
return res;
}
}s;
void dfs(int now,int fa)
{
for(int i=head[now];i;i=net[i])
if(to[i]!=fa)
{
dfs(to[i],now);
root[now]=s.merge(root[now],root[to[i]]);
}
ans[now]=s.ask(root[now],1,n,1,now-1);
s.insert(root[now],1,n,now);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs(m,0);
for(int i=1;i<=n;i++)
{
printf("%d",ans[i]);
if(i!=n) printf(" ");
}
return 0;
}