1. 程式人生 > >Apple Tree POJ - 3321(線段樹+dfs序)

Apple Tree POJ - 3321(線段樹+dfs序)

Apple Tree POJ - 3321

題目連線

題意:一棵蘋果樹,初始每個節點上都有一個蘋果,共n個節點,m個操作,分兩種:
Q x:x節點的子樹中共有多少個蘋果;
C x:若x節點處有蘋果,就摘掉,反之就長出蘋果;
思路:根據樹的dfs序將樹轉換線性問題,再利用線段樹求解;

#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn=1e5+10;
struct Edge{
    int v, nxt;
    Edge(){}
    Edge(int
v0, int n){ v=v0, nxt=n; } }edge[maxn<<1]; int head[maxn], cnt; void add(int u, int v){ edge[cnt]=Edge(v, head[u]); head[u]=cnt++; } int l[maxn], r[maxn], num;//l[x],r[x]分別表示樹上的結點x的子樹的左右區間; void dfs(int u, int fa){ l[u]=++num; for(int i=head[u]; i!=-1; i=edge[i].nxt){ int
v=edge[i].v; if(v==fa) continue; dfs(v, u); } r[u]=num; } struct node{ int l, r, sum; }tr[maxn<<2]; void pushup(int m){ tr[m].sum=tr[m<<1].sum+tr[m<<1|1].sum; } void build(int m, int l, int r){ tr[m].l=l; tr[m].r=r; if(l==r){ tr[m
].sum=1; return; } int mid=(l+r)>>1; build(m<<1, l, mid); build(m<<1|1, mid+1, r); pushup(m); } void updata(int m, int inx){ if(tr[m].l==tr[m].r){ tr[m].sum=(tr[m].sum+1)%2; return; } int mid=(tr[m].l+tr[m].r)>>1; if(inx<=mid) updata(m<<1, inx); else updata(m<<1|1, inx); pushup(m); } int query(int m, int l, int r){ if(tr[m].l==l&&tr[m].r==r){ return tr[m].sum; } int mid=(tr[m].l+tr[m].r)>>1; if(r<=mid) return query(m<<1, l, r); else if(l>mid) return query(m<<1|1, l, r); else return query(m<<1, l, mid)+query(m<<1|1, mid+1, r); } int main(){ int n, m; while(~scanf("%d", &n)){ memset(head, -1, sizeof(head)); cnt=0; for(int i=1; i<n; i++){ int u, v; scanf("%d%d", &u, &v); add(u, v); add(v, u); } num=0; dfs(1, 1); build(1, 1, num); scanf("%d", &m); while(m--){ char op[5]; int x; scanf("%s%d", op, &x); if(op[0]=='Q'){ printf("%d\n", query(1, l[x], r[x])); } else{ updata(1, l[x]); } } } return 0; }