https://www.zybuluo.com/ysner/note/1282069

题面

给一颗带点权的树,求每个点的子树中比该点权值大的点的个数。

  • \(n\leq10^5\)

解析

首先有个很无脑的方法。

用一个权值树状数组维护所有点权(离散化后的)。

每到一个点,询问比该点大的数的个数,然后把这个点权加入树状数组。

dfs回溯以后,再次询问,用这次答案减去上次答案。

这样可以在每个点上直接询问答案。

复杂度\(O(nlog^2n)\)。常数巨小。

然而我做这道题是想入门线段树合并。

其实思想正好相反。

我们不删点权,只把信息从下面合并上来。

对每个点,把它儿子的值域线段树与自己合并。

具体来说是从根节点出发,统计根结点的值,然后合并左儿子右儿子。

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define ll long long
#define re register
#define il inline
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int N=5e5+100,M=1e7;
struct Edge{int to,nxt;}e[N<<1];
int a[N],w[N],n,h[N],cnt,tot,ans[N],rt[M],s[M],ls[M],rs[M],tim;
il void add(re int u,re int v){e[++cnt]=(Edge){v,h[u]};h[u]=cnt;}
il ll gi()
{
re ll x=0,t=1;
re char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') t=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*t;
}
il void Modify(re int &x,re int l,re int r,re int W)
{
if(!x) x=++tim;
++s[x];
if(l==r) return;
re int mid=l+r>>1;
if(W<=mid) return Modify(ls[x],l,mid,W);
return Modify(rs[x],mid+1,r,W);
}
il int Query(re int x,re int l,re int r,re int W)
{
if(!x) return 0;
if(l>=W) return s[x];
re int mid=l+r>>1;
if(W<=mid) return Query(ls[x],l,mid,W)+Query(rs[x],mid+1,r,W);
return Query(rs[x],mid+1,r,W);
}
il int Merge(re int u,re int v)
{
if(!u) return v;if(!v) return u;
re int p=++tim;
s[p]=s[u]+s[v];
ls[p]=Merge(ls[u],ls[v]);
rs[p]=Merge(rs[u],rs[v]);
return p;
}
il void dfs(re int u)
{
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to;
dfs(v);
rt[u]=Merge(rt[u],rt[v]);
}
ans[u]=Query(rt[u],1,tot,w[u]+1);
Modify(rt[u],1,tot,w[u]);
}
int main()
{
memset(h,-1,sizeof(h));
n=gi();
fp(i,1,n) a[i]=w[i]=gi();
fp(v,2,n)
{
re int u=gi();
add(u,v);
}
sort(a+1,a+1+n);
tot=unique(a+1,a+1+n)-a-1;
fp(i,1,n) w[i]=lower_bound(a+1,a+1+tot,w[i])-a;
dfs(1);
fp(i,1,n) printf("%d\n",ans[i]);
return 0;
}

最新文章

  1. java动态编译笔记
  2. UDS(ISO14229-2006) 汉译(No.3术语与定义)
  3. 转《UNIX编程艺术》读书心得
  4. Java中基本数据类型的对比记忆
  5. [MCSM]伪随机数和伪随机数生成器
  6. jira插件带ui界面和几种方式
  7. mysql死锁示例
  8. 基于python3的手机号生成脚本
  9. SQL语句备忘
  10. 在 SharePoint 2010 中访问数据
  11. SQL Server调试常用参数
  12. Quartz CronTrigger应用
  13. 教你自己搭建linux邮箱服务器
  14. FPGA调试光纤模块
  15. Jumbo frame与MTU
  16. 将Emacs Org任务树导出至Freeplane思维导图
  17. Maven安装问题
  18. yum搭建 Lamp环境
  19. The host '192.168.174.130' is unreachable. the host may be down..............
  20. 聚类——K-means

热门文章

  1. table JS合并单元格
  2. 第七章习题G题
  3. jz2440开发板烧写裸板
  4. Linux学习总结(22)——CentOS7.2安装Nginx
  5. STM32F407 跑马灯 库函数版 个人笔记
  6. GitHub &amp; puppeteer &amp; Chinese character &amp; bug
  7. POJ1094 字母排序(拓扑排序)
  8. Flask(1):基本示例、配置文件、路由、请求和响应、模板渲染
  9. [bzoj1112][POI2008]砖块Klo_非旋转Treap
  10. UEFI 下安装 ubuntu 及 win8 双系统 的一些事