https://nanti.jisuanke.com/t/20690

武当派一共有 nn 人,门派内 nn 人按照武功高低进行排名,武功最高的人排名第 11,次高的人排名第 22,... 武功最低的人排名第 nn。现在我们用武功的排名来给每个人标号,除了祖师爷,每个人都有一个师父,每个人可能有多个徒弟。

我们知道,武当派人才辈出,连祖师爷的武功都只能排行到 pp。也就是说徒弟的武功是可能超过师父的,所谓的青出于蓝胜于蓝。

请你帮忙计算每个人的所有子弟(包括徒弟的徒弟,徒弟的徒弟的徒弟....)中,有多少人的武功超过了他自己。

输入格式

输入第一行两个整数 n,p(1≤n≤100000,1≤p≤n)n,p(1≤n≤100000,1≤p≤n)。

接下来 n−1n−1 行,每行输入两个整数 u,v(1≤u,v≤n)u,v(1≤u,v≤n),表示 uu 和 vv 之间存在师徒关系。

输出格式

输出一行 nn 个整数,第 ii 个整数表示武功排行为 ii的人的子弟有多少人超过了他。

通过求dfs序,将子树上的问题转化为序列上的问题,然后用线段树求小于某个数的数的个数。

#include <cstdio>

#include <iostream>

#include <vector>

#include <queue>

using namespace std;

#define lc (rt << 1)

#define rc (rt << 1 | 1)

#define mid (l + r) / 2

const int maxn = 1e5 + 5;

vector<int> mp[maxn];

int f[maxn];

int te = 1;

int s[maxn],t[maxn];

int mmin[maxn << 2],mmax[maxn << 2];

int pre[maxn];

int prep = 1;

int ans[maxn];

int n,p;

void dfs(int p)

{

s[p] = ++te;

pre[prep ++] = p;

for (int i = 0; i < mp[p].size(); i ++) {

if(s[mp[p][i]] == 0) {

dfs(mp[p][i]);

}

else f[p] = mp[p][i];

}

t[p] = te;

}

void init(int l,int r,int rt)

{

if(l == r){

mmin[rt] = mmax[rt] = pre[l];

return;

}

init(l, mid, lc);

init(mid + 1, r, rc);

mmax[rt] = max(mmax[lc],mmax[rc]);

mmin[rt] = min(mmin[lc],mmin[rc]);

}

int querymmin(int ql,int qr,int l,int r,int rt)

{

if(ql <= l && r <= qr){

return mmin[rt];

}

int ans = maxn;

if(ql <= mid) ans = min(ans,querymmin(ql, qr, l, mid , lc));

if(mid < qr) ans = min(ans,querymmin(ql, qr, mid + 1, r, rc));

return ans;

}

int querymmax(int ql,int qr,int l,int r,int rt)

{

if(ql <= l && r <= qr){

return mmax[rt];

}

int ans = 0;

if(ql <= mid) ans = max(ans,querymmax(ql, qr, l, mid , lc));

if(mid < qr) ans = max(ans,querymmax(ql, qr, mid + 1, r, rc));

return ans;

}

int querycnt(int ql,int qr,int l,int r,int rt,int x)//求区间中比x小的数的个数

{

if(ql <= l && r <= qr){

if(querymmax(ql, qr, l, r, rt) < x ) return r - l + 1;

else {

if(querymmin(ql, qr, l, r, rt) >= x)return 0;

else return querycnt(ql, qr, l, mid, lc, x) + querycnt(ql, qr, mid + 1, r, rc, x);

}

}

int ans = 0;

if(ql <= mid){

ans += querycnt(ql,qr,l,mid,lc,x);

}

if(mid < qr){

ans += querycnt(ql,qr,mid + 1,r,rc,x);

}

return ans;

}

int main()

{

int a,b;

f[p] = -1;

scanf("%d%d",&n,&p);

for (int i = 0; i < n - 1; i ++) {

scanf("%d%d",&a,&b);

mp[a].push_back(b);

mp[b].push_back(a);

}

dfs(p);

init(1, n, 1);

for (int i = 1; i <= n; i ++) {

ans[pre[i]] = querycnt(s[pre[i]] - 1, t[pre[i]] - 1, 1, n,1 ,pre[i]);

//  printf("l = %d ,r = %d ,less than %d ,cnt = %d\n",s[pre[i]] - 1, t[pre[i]] - 1,pre[i],ans[pre[i]]);

}

for (int i = 1; i<= n; i ++) {

printf("%d",ans[i]);

if(i == n) printf("\n");

else printf(" ");

}

return 0;

}

dfs序+线段树--青出于蓝胜于蓝相关推荐

  1. New Year Tree(dfs序+线段树+二进制)

    题意: 给出一棵 n个节点的树,根节点为 1.每个节点上有一种颜色 ci.m次操作.操作有两种: 1 u c:将以 u为根的子树上的所有节点的颜色改为c. 2 u:询问以 u为根的子树上的所有节点的颜 ...

  2. 求和(dfs序+线段树)

    题意: 已知有n个节点,有n−1条边,形成一个树的结构. 给定一个根节点k,每个节点都有一个权值,节点i的权值为vi​. 给m个操作,操作有两种类型: 1 a x :表示将节点a的权值加上x 2 a ...

  3. 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

    题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...

  4. codeforces E. Jamie and Tree LCA+dfs序+线段树

    题解: 写起来还稍微有点麻烦. dfs序+线段树可以维护子树的整体修改和查询. 因此,这道题我们要往子树上靠. 我们首先从1号点进行dfs遍历,顺便求出点的dfs序和深度,然后我们采用倍增的思想,可以 ...

  5. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  6. [CodeForces877 E. Danil and a Part-time Job]dfs序+线段树

    [CodeForces877 E.Danil and a Part-time Job]dfs序+线段树 分类:Data Structure SegMent Tree dfn 1. 题目链接 [Code ...

  7. bzoj3252攻略 贪心+dfs序+线段树

    题目链接:戳这里 3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 605  Solved: 255 [Submit][Status] ...

  8. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 339  Solved: 130 [Submit][Status][Discuss] ...

  9. dfs序+线段树 BZOJ3252 攻略

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 496  Solved: 211 [Submit][Status][Discuss] ...

  10. Jittery Roads Gym - 100889J (虚树 + DP + dfs 序, + 线段树)

    每次给一个点集, 求每个点到其他所有点的最大距离: 会修改边权; 修改边权之后, 我们可以用 dfs 序 + 线段树维护 当前点到根节点的距离. 还可以用树状数组 + 差分思想 维护. { dfs 序 ...

最新文章

  1. 使GDAL库支持中文路径或中文文件名的处理方法
  2. HTML用乘法函数,Excel乘法函数的使用方法和详细步骤
  3. jboss1.7_在JBoss Fuse / Fabric8 / Karaf中使用Byteman
  4. android耳机广播,Android利用广播实现耳机的线控
  5. 如何设计通用的网站模板
  6. 关于MySQL 8.0
  7. 在Corporate Network里配置SAP Cloud Connector连接SAP云平台,需要设置代理
  8. java文章上一篇下一篇_每个人都必须阅读的10篇Java文章
  9. 光纤收发器常见的一些问题和检测方法
  10. php打开rs232,php_ser_5.2.0-5.2.17
  11. 浅谈对象生存期与内存管理(转)
  12. 泰坦尼克号python数据分析统计服_Python数据分析及可视化实例之泰坦尼克号存活预测(23)...
  13. cad图纸比对lisp_cad图纸怎么找出差异?教你怎么对比CAD图纸版本差异
  14. B. Neko Performs Cat Furrier Transform---异或的性质运用--Codeforces Round #554 (Div. 2)
  15. Unity_触摸屏_720全景制作
  16. Hexo添加Icarus主题
  17. 企业微信裂变玩法有哪些?需要使用哪些工具?
  18. Vue源码学习 -- 响应式原理之观察者模式
  19. 年轻人纵横职场高情商话术
  20. C++使用TinyXml2解析Xml

热门文章

  1. promise、axios 理解
  2. 通过负载均衡器+域名实现容灾切换-(11)深信服负载均衡器
  3. go每日新闻--2021-01-16
  4. 13个最狂帅炫酷的前沿科技研究项目
  5. C# Email发送邮件
  6. Parallels Desktop 安装 Win7注意事项
  7. 俞敏洪+马云+牛根生+史玉柱经典语录
  8. 用python画雨滴_python实现雨滴下落到地面效果
  9. Win10 - 打开资源管理器显示的不是磁盘
  10. 常见python基础面试题_常的解释|常的意思|汉典“常”字的基本解释