POJ 3321 Apple Tree (DFS + 樹狀數組)

題意:

一棵蘋果樹有N個分叉,編號1---N(根的編號爲1),每個分叉只能有一顆蘋果或者沒有蘋果。 現在有兩種操作:

1.某個分叉上的蘋果從有變無或者從無邊有。

2.需要統計以某個分叉爲根節點時,它的子樹上(包括該分叉)共有多少蘋果。


分析: 有兩種操作,基本就是使用數據結構維護的題目了。開始想了很久,不懂如何將分叉轉化爲一維線性的樹狀數組維護。 看了下discuss,有人說了時間戳三字。想了想,發現如果按照節點遍歷的順序可以製造出時間上的線性關係。 例如:

連接情況爲:1---->2     1--->3    3--->4        3--->5

以1爲根節點開始dfs,則遍歷到每個點的時間可以爲       1---->1     3--->2    4--->3    5---->4     2--->5

用兩個數組begin,end統計以節點i爲根時,遍歷的第一個點的時間,和遍歷最後一個點的時間

所以:begin[1] = 1 ;  end[1] = 5;   begin[2] = 5 ; end[2] = 5;   begin[3] = 2; end[3] = 4;........................................................

改變節點i的狀態,時間戳小於i的會受影響;求和時,只需求(begin[i],end[i])的和了............................這樣就變成了單點更新,區間求和的問題了。


#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <climits>//形如INT_MAX一類的
#define MAX 100005
#define INF 0x7FFFFFFF
#define REP(i,s,t) for(int i=(s);i<=(t);++i)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#define L(x) x<<1
#define R(x) x<<1|1
# define eps 1e-5
//#pragma comment(linker, "/STACK:36777216") ///傳說中的外掛
using namespace std;

int begin[MAX],end[MAX],cnt[MAX],vis[MAX];
int c[MAX];
int n,m,step;
char op;
struct node {
    int s,e,next;
} ed[MAX];
int head[MAX],num;

void init() {
    memset(head,-1,sizeof(head));
    num = 0;
    step = 1;
    memset(c,0,sizeof(c));
    memset(cnt,1,sizeof(cnt));
    memset(vis,0,sizeof(vis));
}

void addedge(int s,int e) {
    ed[num].s = s;
    ed[num].e = e;
    ed[num].next = head[s];
    head[s] = num ++;
}

int lowbit(int x) {
    return x & (-x);
}

void update(int x,int va) {
    while(x > 0) {
        c[x] += va;
        x -= lowbit(x);
    }
}

int query(int x) {
    int sum = 0;
    while(x <= n) {
        sum += c[x];
        x += lowbit(x);
    }
    return sum;
}

void dfs(int v0) {
    vis[v0] = 1;
    begin[v0] = step;
    for(int i=head[v0]; i != -1; i = ed[i].next) {
        int e = ed[i].e;
        if(vis[e] == 0) {
            step ++;
            dfs(e);
        }
    }
    end[v0] = step;
}

int main() {
    init();
    scanf("%d",&n);
    int x,y;
    for(int i=0; i<n-1; i++) {
        scanf("%d%d",&x,&y);
        addedge(x,y);
    }
    dfs(1);
    for(int i=1; i<=n; i++) update(i,1);
    scanf("%d",&m);
    for(int i=0; i<m; i++) {
        getchar();
        scanf("%c%d",&op,&x);
        if(op == 'Q') {
            printf("%d\n",query(begin[x]) - query(end[x] + 1));
        }
        if(op == 'C') {
            cnt[x] ++;
            if(cnt[x] % 2 == 0) update(begin[x],-1);
            else update(begin[x],1);
        }
    }
    return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章