Apple Tree POJ - 3321(線段樹+dfs序)
阿新 • • 發佈:2018-12-01
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;
}