POJ 3321 Apple Tree 【树形结构转变为线性结构+线段树OR树状数组】

Apple Tree

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 21587   Accepted: 6551

POJ 3321链接:

Description

There is an apple tree outside of kaka‘s house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been carefully nurturing the big apple tree.

The tree has N forks which are connected by branches. Kaka numbers the forks by 1 to N and the root is always numbered by 1. Apples will grow on the forks and two apple won‘t grow on the same fork. kaka wants to know how many apples are
there in a sub-tree, for his study of the produce ability of the apple tree.

The trouble is that a new apple may grow on an empty fork some time and kaka may pick an apple from the tree for his dessert. Can you help kaka?

Input

The first line contains an integer N (N ≤ 100,000) , which is the number of the forks in the tree.

The following N - 1 lines each contain two integers u and v, which means fork u and fork v are connected by a branch.

The next line contains an integer M (M ≤ 100,000).

The following M lines each contain a message which is either

"x" which means the existence of the apple on fork x has been changed. i.e. if there is an apple on the fork, then Kaka pick it; otherwise a new apple has grown on the empty fork.

or

"x" which means an inquiry for the number of apples in the sub-tree above the fork x, including the apple (if exists) on the fork x

Note the tree is full of apples at the beginning

Output

For every inquiry, output the correspond answer per line.

Sample Input

3
1 2
1 3
3
Q 1
C 2
Q 1

Sample Output

3
2

励志一下

每一个你讨厌的现在,都有一个不够努力的曾经

题外话

这个题目我认为出得特别好,非常启发思维,线段树专题必刷之题啊!!!话不扯远了,让咱们言归正传,开始讲题。

题意

一棵具有n个节点的树,一开始,每个节点上都有一个苹果。现在给出m组操作:(C,i)是摘掉第i个节点上面的苹果(若苹果不存在,则为加上一个苹果),(Q,i)是查询以第i个节点为根的子树有几个苹果(包括第i个节点)。

分析

Step 1:

如下图,可以看到,由于普通的树并不具有区间的性质,所以在考虑使用线段树作为解题思路时,需要对给给定的数据进行转化,首先对这棵树进行一次dfs遍历,记录dfs序下每个点访问起始时间与结束时间,记录起始时间是前序遍历,结束时间是后序遍历,同时对这课树进行重标号。

Step 2:

如下图,DFS之后,那么树的每个节点就具有了区间的性质。

那么此时,每个节点对应了一个区间,而且可以看到,每个节点对应的区间正好“管辖”了它子树所有节点的区间,那么对点或子树的操作就转化为了对区间的操作。

【PS: 如果对树的遍历看不懂的话,不妨待会对照代码一步一步调试,或者在纸上模拟过程~】

Step 3:

这个时候,每次对节点进行更新或者查询,就是线段树和树状数组最基本的实现了…

代码实现

那我下面分别 给出线段树和树状数组的两种实现吧。

/****************************>>>>HEADFILES<<<<****************************/
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <algorithm>
using namespace std;
/****************************>>>>>DEFINE<<<<<*****************************/
#define fst             first
#define snd             second
#define root            1,N,1
#define lson            l,mid,rt<<1
#define rson            mid+1,r,rt<<1|1
#define PB(a)           push_back(a)
#define MP(a,b)         make_pair(a,b)
#define CASE(T)         for(scanf("%d",&T);T--;)
#define FIN             freopen("input.txt","r",stdin)
#define FOUT            freopen("output.txt","w",stdout)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef __int64         LL;
typedef pair<int,int>   PII;
const int INF = 0x3f3f3f3f;
const int maxn = 100000 + 5;
/****************************>>>>SEPARATOR<<<<****************************/
struct Node { int fir,las; }nodes[maxn];
vector<vector<int> > G;
bool vis[maxn];
int segtree[maxn << 2];
int G_Mark, N, M, u, v;
void init()
{
    G.resize(N+2);
    G_Mark = 0;
    G.clear();
    memset(vis, false, sizeof(vis));
}
void DFS(int x)
{
    vis[x] = true;
    nodes[x].fir = ++G_Mark;
    for(int i = 0; i < G[x].size(); i++)
    {
        if(vis[G[x][i]]) continue;
        DFS(G[x][i]);
    }
    nodes[x].las = G_Mark;
}
inline void PushUp(int rt)
{
    segtree[rt] = segtree[rt << 1] + segtree[rt << 1 | 1];
}
void Build(int l, int r, int rt)
{
    segtree[rt] = r - l + 1;
    if(l == r) return;
    int mid = (l + r) >> 1;
    Build(lson);
    Build(rson);
}
void Update(const int& pos, int l, int r, int rt)
{
    if(l == r)
    {
        segtree[rt] ^= 1;
        return;
    }
    int mid = (l + r) >> 1;
    if(pos <= mid) Update(pos, lson);
    else Update(pos, rson);
    PushUp(rt);
}
int Query(const int& L, const int& R, int l, int r, int rt)
{
    if(L <= l && r <= R)
        return segtree[rt];
    int mid = (l + r) >> 1, ret = 0;
    if(L <= mid) ret += Query(L, R, lson);
    if(R > mid) ret += Query(L, R, rson);
    return ret;
}
int main()
{
   // FIN;
    while(~scanf("%d", &N))
    {
        init();
        for(int i = 0; i < N - 1; i++)
        {
            scanf("%d %d", &u, &v);
            G[u].PB(v);
            G[v].PB(u);
        }
        DFS(1);
        scanf("%d", &M);
        char Op[5];
        int x, pos, L, R, ans;
        Build(root);
        for(int i = 0; i < M; i++)
        {
            scanf("%s %d", Op, &x);
            if(Op[0] == 'C')
            {
                pos = nodes[x].fir;
                Update(pos, root);
            }
            else
            {
                L = nodes[x].fir, R = nodes[x].las;
                ans = Query(L, R, root);
                printf("%d\n", ans);
            }
        }
    }
    return 0;
}
/****************************>>>>HEADFILES<<<<****************************/
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <algorithm>
using namespace std;
/****************************>>>>>DEFINE<<<<<*****************************/
#define fst             first
#define snd             second
#define root            1,N,1
#define lson            l,mid,rt<<1
#define rson            mid+1,r,rt<<1|1
#define PB(a)           push_back(a)
#define MP(a,b)         make_pair(a,b)
#define CASE(T)         for(scanf("%d",&T);T--;)
#define FIN             freopen("input.txt","r",stdin)
#define FOUT            freopen("output.txt","w",stdout)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef __int64         LL;
typedef pair<int,int>   PII;
const int INF = 0x3f3f3f3f;
const int maxn = 100000 + 5;
/****************************>>>>SEPARATOR<<<<****************************/
struct Node { int fir,las; }nodes[maxn];
vector<vector<int> > G;
bool vis[maxn];
int C[maxn],S[maxn];
int G_Mark, N, M, u, v;
void init()
{
    G.resize(N+2);
    G_Mark = 0;
    G.clear();
    memset(C,0,sizeof(C));
    memset(vis, false, sizeof(vis));
}
void DFS(int x)
{
    vis[x] = true;
    nodes[x].fir = ++G_Mark;
    for(int i = 0; i < G[x].size(); i++)
    {
        if(vis[G[x][i]]) continue;
        DFS(G[x][i]);
    }
    nodes[x].las = G_Mark;
}
inline int lowbit(int x) { return x&(x^(x-1)); }
void Add(int pos,int val)
{
    while(pos <= N)
    {
        C[pos] += val;
        pos += lowbit(pos);
    }
}
int Sum(int pos)
{
    int ret = 0;
    while(pos > 0)
    {
        ret += C[pos];
        pos -= lowbit(pos);
    }
    return ret;
}
int main()
{
   // FIN;
    while(~scanf("%d", &N))
    {
        init();
        for(int i = 0; i < N - 1; i++)
        {
            scanf("%d %d", &u, &v);
            G[u].PB(v);
            G[v].PB(u);
        }
        DFS(1);
        scanf("%d", &M);
        char Op[5];
        int x, pos, L, R, ans;
        for(int i = 1;i <= N;i++) Add(i,1),S[i] = 1;
        for(int i = 0; i < M; i++)
        {
            scanf("%s %d", Op, &x);
            if(Op[0] == 'C')
            {
                pos = nodes[x].fir;
                S[pos] ^= 1;
                int add = S[pos] == 1 ? 1 : -1;
                Add(pos,add);
            }
            else
            {
                L = nodes[x].fir, R = nodes[x].las;
                if(L == 1) ans = Sum(R);
                else ans = Sum(R) - Sum(L-1);
                printf("%d\n", ans);
            }
        }
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-21 11:34:25

POJ 3321 Apple Tree 【树形结构转变为线性结构+线段树OR树状数组】的相关文章

POJ 3321—— Apple Tree(树状数组)

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 19160   Accepted: 5831 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been

poj 3321:Apple Tree(树状数组,提高题)

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 18623   Accepted: 5629 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been

POJ - 3321 Apple Tree (线段树 + 建树 + 思维转换)

POJ - 3321 Apple Tree Time Limit: 2000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Submit Status Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very muc

【树状数组】POJ 3321 Apple Tree

/** * @author johnsondu * @time 2015.8.25 20:04 * @problem POJ 3321 Apple Tree * @type Binary Index Tree * @description 从根节点开始,dfs遍历树,先访问的节点 * 记为beg, 从当前结点遍历访问到的最后的 * 一个节点,记为end.然后按照树状数组的 * 方法进行求解. * @url http://poj.org/problem?id=3321 */ #include <i

POJ 3321 Apple Tree (dfs+线段树)

题目大意: 修改树上的节点,然后求子树的和. 思路分析: dfs 重新编号,烂大街了... #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #define maxn 100005 #define lson num<<1,s,mid #define rson num<<1|1,mid+1,e using namespace std

POJ 3321 Apple Tree 【树状数组+建树】

题目链接:http://poj.org/problem?id=3321 Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 34812 Accepted: 10469 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka like

POJ 3321 Apple Tree (树状数组)

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 21191   Accepted: 6436 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been

POJ 3321 Apple Tree

题目链接:http://poj.org/problem?id=3321 解题思路:dfs加时间戳然后简单树状数组单点更新区间查询即可. 代码: 1 const int maxn = 1e5 + 5; 2 struct Edge{ 3 int to, next; 4 }; 5 Edge edges[maxn]; 6 int head[maxn], tot; 7 int st[maxn], ed[maxn], cnt; 8 int bit[maxn], status[maxn], n, m; 9 1

#5 DIV2 A POJ 3321 Apple Tree 摘苹果 构建线段树

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 25232   Accepted: 7503 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been