您的位置:首页 > Web前端

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

2017-05-08 21:00 344 查看

传送门

 

这个题显然可以用树链剖分做。

然而线段树也能做。

每个点都对它的子树有贡献,所以先求一边 dfs序,然后直接在 dfs序 中搞 线段树 就行。

 

——代码

#include <cstdio>
#include <cstring>
#define root 1, 1, n
#define ls now << 1, l, mid
#define rs now << 1 | 1, mid + 1, r

using namespace std;

const int MAXN = 100001;
int n, cnt, tim;
int head[MAXN], to[MAXN << 1], next[MAXN << 1], add[MAXN << 2], tid[MAXN], size[MAXN];

inline void add_edge(int x, int y)
{
to[cnt] = y;
next[cnt] = head[x];
head[x] = cnt++;
}

inline void dfs(int u)
{
int i, v;
tid[u] = ++tim;
size[u] = 1;
for(i = head[u]; i != -1; i = next[i])
{
v = to[i];
if(!size[v]) dfs(v), size[u] += size[v];
}
}

inline void push_down(int now)
{
if(!add[now]) return;
add[now << 1] += add[now];
add[now << 1 | 1] += add[now];
add[now] = 0;
}

inline int query(int x, int now, int l, int r)
{
if(l == r) return add[now];
push_down(now);
int mid = (l + r) >> 1;
if(x <= mid) return query(x, ls);
else return query(x, rs);
}

inline void update(int x, int y, int now, int l, int r)
{
if(x <= l && r <= y)
{
add[now]++;
return;
}
if(l > y || r < x) return;
push_down(now);
int mid = (l + r) >> 1;
update(x, y, ls);
update(x, y, rs);
}

int main()
{
int i, x, y;
scanf("%d", &n);
memset(head, -1, sizeof(head));
for(i = 1; i < n; i++)
{
scanf("%d %d", &x, &y);
add_edge(x, y);
add_edge(y, x);
}
dfs(1);
for(i = 1; i <= n; i++)
{
scanf("%d", &x);
printf("%d\n", query(tid[x], root));
update(tid[x], tid[x] + size[x] - 1, root);
}
return 0;
}
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: