线段树  树的dfs序

来自   洛谷 P1982   的翻译

by  GeneralLiu

来自 jzyz 的翻译 %mzx

线段树  dfs序

数据结构的应用

“数据结构 是先有需求 再有应用” by mzx

那么按照这个思路

先看看针对这道题 有什么需求

再考虑用什么数据结构去解决

以及怎么用该数据结构

这是一个树上的题

某个人进了寝室

只会影响到他子树的答案

因为只有他的 子树 回寝室时

要经过他 得slowing down对吧

这时 要对他的 子树的答案全部 区间+1

这是 对dfs序的需求

需要 dfs序 将树转换成区间

区间修改 单点查询 又是对 线段树 的需求

需要 线段树 的高效维护

如有dalao有更高效的方法请博客留言

我目前只学了线段树这个家伙啦

具体应用

dfs序

void dfs(int u){
dfn[u]=++cnt;//dfn[]为树转换为dfs序中的下标
size[u]=1;//u为根的子树大小
int v;
for(int i=head[u];i;i=next[i]){
v=to[i];
if(dfn[v])continue;
dfs(v);
size[u]+=size[v];
}
}

这样一棵子树 就对应了 dfn[]数组 的一段区间

 以点k为根的 区间

  左端点 是 dfn[k],

  右端点 是 dfn[k] + size [k] - 1 。

线段树

main() 函数中的代码

for(int k,i=1;i<=n;i++){
k=read(); //单点查询
printf("%d\n",query(dfn[k],root)); //区间修改
update(dfn[k],dfn[k]+size[k]-1,root);
} 其他函数 void pushdown(int rt){//懒标记下传
if(!add[rt])return;
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
add[rt]=0;
}
void update(int x,int y,int l,int r,int rt){
if(x<=l&&r<=y){
add[rt]++;//区间修改时 针对本题 懒标记+1
return;
}
pushdown(rt);
int mid=(l+r)>>1;
if(x<=mid)update(x,y,lson);
if(mid<y)update(x,y,rson);
}
int query(int k,int l,int r,int rt){
//单点查询 所以线段树只用 懒标记add[]数组 即可
if(l==r)return add[rt];
pushdown(rt);
int mid=(l+r)>>1;
if(k<=mid)return query(k,lson);
return query(k,rson);
}

这样就 滋瓷 了本题的修改与查询操作

总代码

#include<bits/stdc++.h>
using namespace std;
#define N 100015
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
int n,cnt;
int head[N],next[N<<1],to[N<<1];
int dfn[N],size[N];
int add[N<<2];
int read(){
int ans=0;
char ch=getchar();
for(;!isdigit(ch);ch=getchar());
for(;isdigit(ch);ch=getchar())
ans=(ans<<3)+(ans<<1)+ch-'0';
return ans;
}
void ad(int from,int too){
next[++cnt]=head[from];
to[cnt]=too;
head[from]=cnt;
}
void dfs(int u){
dfn[u]=++cnt;//dfn[]为树转换为dfs序中的下标
size[u]=1;//u为根的子树大小
int v;
for(int i=head[u];i;i=next[i]){
v=to[i];
if(dfn[v])continue;
dfs(v);
size[u]+=size[v];
}
}
void pushdown(int rt){//懒标记下传
if(!add[rt])return;
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
add[rt]=0;
}
void update(int x,int y,int l,int r,int rt){
if(x<=l&&r<=y){
add[rt]++;//区间修改时 针对本题 懒标记+1
return;
}
pushdown(rt);
int mid=(l+r)>>1;
if(x<=mid)update(x,y,lson);
if(mid<y)update(x,y,rson);
}
int query(int k,int l,int r,int rt){
//单点查询 所以线段树只用 懒标记add[]数组 即可
if(l==r)return add[rt];
pushdown(rt);
int mid=(l+r)>>1;
if(k<=mid)return query(k,lson);
return query(k,rson);
}
int main(){
n=read();
for(int x,y,i=1;i<n;i++){
x=read(),y=read();
ad(x,y);
ad(y,x);
}
cnt=0;
dfs(1);
for(int k,i=1;i<=n;i++){
k=read(); //单点查询
printf("%d\n",query(dfn[k],root)); //区间修改
update(dfn[k],dfn[k]+size[k]-1,root);
}
return 0;
}

  

[USACO10FEB]慢下来Slowing down的更多相关文章

  1. USACO10FEB]慢下来Slowing down dfs序 线段树

    [USACO10FEB]慢下来Slowing down 题面 洛谷P2982 本来想写树剖来着 暴力数据结构直接模拟,每头牛回到自己的农场后,其子树下的所有牛回到农舍时,必定会经过此牛舍,即:每头牛回 ...

  2. 洛谷P2982 [USACO10FEB]慢下来Slowing down [2017年四月计划 树状数组01]

    P2982 [USACO10FEB]慢下来Slowing down 题目描述 Every day each of Farmer John's N (1 <= N <= 100,000) c ...

  3. 洛谷P2982 [USACO10FEB]慢下来Slowing down(线段树 DFS序 区间增减 单点查询)

    To 洛谷.2982 慢下来Slowing down 题目描述 Every day each of Farmer John's N (1 <= N <= 100,000) cows con ...

  4. [luogu2982][USACO10FEB]慢下来Slowing down(树状数组+dfs序)

    题目描述 Every day each of Farmer John's N (1 <= N <= 100,000) cows conveniently numbered 1..N mov ...

  5. 洛谷P2982 [USACO10FEB]慢下来Slowing down

    题目 题目大意 :给出一棵树,节点有点权,求每个节点的祖先中点权小于该节点的结点的个数 . 思路如下 : 从根节点开始,对树进行深度优先遍历. 当进行到节点 i 时,有: $\text{i}$ ​的祖 ...

  6. luoguP2982 [USACO10FEB]慢下来Slowing down

    https://www.luogu.org/problemnew/show/P2982 这题你写个树剖当然可以做,但是我们还有一种更简单的方法,使用 dfs 序 + 树状数组即可 考虑一只牛到了自己的 ...

  7. 线段树+Dfs序【p2982】[USACO10FEB]慢下来Slowing down

    Description 每天Farmer John的N头奶牛(1 <= N <= 100000,编号1-N)从粮仓走向他的自己的牧场.牧场构成了一棵树,粮仓在1号牧场.恰好有N-1条道路直 ...

  8. 洛谷 P2982 [USACO10FEB]慢下来Slowing down

    题目描述 Every day each of Farmer John's N (1 <= N <= 100,000) cows conveniently numbered 1..N mov ...

  9. [luoguP2982][USACO10FEB]慢下来Slowing down(dfs序 + 线段树)

    传送门 这个题显然可以用树链剖分做. 然而线段树也能做. 每个点都对它的子树有贡献,所以先求一边 dfs序,然后直接在 dfs序 中搞 线段树 就行. ——代码 #include <cstdio ...

随机推荐

  1. poj3252Round Numbers

    链接 也算是组合 以前按组合做过一次 忘记怎么做的了 这次按dp写的 dp[i][j][g][k] 表示第i位为k(0|1)而且有j个1,g个0的情况数 貌似写的麻烦了...这一类的题,进行逐位计算就 ...

  2. CF985E Pencils and Boxes

    思路: 先对a数组排序,然后使用动态规划.dp[i]表示前i个能否正确划分.则如果存在dp[j] == 1, i - j + 1 >= k并且a[i] - a[j] < d,那么dp[i] ...

  3. UOJ#52. 【UR #4】元旦激光炮(交互)

    题意 给出三个已经排好序的数组$a, b, c$ 在$100$次询问内找出第$k$小的元素 Sol 一种很显然的$log^2n$的做法:首先在$a$中二分,然后再$b,c$中二分.这样可以得到$60$ ...

  4. P2712 摄像头

    题目描述 食品店里有n个摄像头,这种摄像头很笨拙,只能拍摄到固定位置.现有一群胆大妄为的松鼠想要抢劫食品店,为了不让摄像头拍下他们犯罪的证据,他们抢劫前的第一件事就是砸毁这些摄像头. 为了便于砸毁摄像 ...

  5. zabbix server端配置

    # wget http://sourceforge.net/projects/zabbix/files/ZABBIX%20Latest%20Stable/2.0.6/zabbix-2.0.6.tar. ...

  6. log4j 日志分级处理

    log4j 配置文件: log4j.rootLogger=debug,stdout,debug,info,errorlog4j.appender.stdout=org.apache.log4j.Con ...

  7. 中间件及tomcat的内存溢出调优

    主要是这三个选项的调整需要根据主机的内存配置 以及业务量的使用情况调节 -Xmx4g -Xms4g -Xmn2g xmx 与xms一般设置为一样 xmn大致设置为xmx xms的三分之一   可以使用 ...

  8. sqlserver 数据库主外键关联错误

    话题引入: 在建立主外键关系时,系统提示表"table2"中的列与现有的主键或UNIQUE约束不匹配 原因: 数据库表中只有一个主键,这个主键可以是多个列共同组成.所以table2 ...

  9. 主成分分析、因子分析、ICA(未完成)

    并且SVD分解也适用于一般的矩阵. 主成分分析可以简单的总结成一句话:数据的压缩和解释.常被用来寻找判断某种事物或现象的综合指标,并且给综合指标所包含的信息以适当的解释.在实际的应用过程中,主成分分析 ...

  10. [LUOGU] P2886 [USACO07NOV]牛继电器Cow Relays

    https://www.luogu.org/problemnew/show/P2886 给定无向连通图,求经过k条边,s到t的最短路 Floyd形式的矩阵乘法,同样满足结合律,所以可以进行快速幂. 离 ...