1. 程式人生 > >poj 3321 dfs序 樹狀陣列 前向星

poj 3321 dfs序 樹狀陣列 前向星

 

題意概括

有一顆01樹,以結點1為樹根,一開始所有的結點權值都是1,有兩種操作:

  1.改變其中一個結點的權值(0變1,1變0)

  2.詢問子樹X的節點權值和。

參考部落格 http://www.cnblogs.com/zhouzhendong/p/7265431.html

思路 :dfs序  +樹狀陣列

題目變成dfs序上   單點修改  和區間sum詢問的問題。

單點修改,不用線段樹,樹狀陣列就可以了

用vector存圖超時。。改用的前向星

#include<cstdio>
#include<iostream>
#include
<algorithm> #include<cmath> #include<cstring> #include<vector> using namespace std; const int N = 1E5+3; const int M = 2E5+3; #define pb push_back int n; int in[N],out[N]; int time; int vis[N]; int tree[N],a[N]; struct edge{ int cnt,y[M],nxt[M],head[N]; void clc(){ cnt
=0 ; memset(head,0,sizeof(head)); } void add(int a,int b){ y[++cnt]=b; nxt[cnt]=head[a];head[a]=cnt; } }E; void dfs(int t){ in[t]=++time; vis[t]=1; for(int i =E.head[t];i;i=E.nxt[i]){ if(vis[E.y[i]])continue; vis[E.y[i]]=1; dfs(E.y[i]); }
out[t]=time; } int lowbit(int x){ return x&-x; } int sum(int x){ int ans=0; for(;x>0;x-= x&-x){ ans+=tree[x]; } return ans; } void update(int x,int val){ for(;x<=n;x+= x&-x) tree[x]+=val; } int main(){ int u,v; char s[22];int x; while(cin>>n){ time=0; memset(vis,0,sizeof(vis)); E.clc(); for(int i=1;i<n;++i){ scanf("%d %d",&u,&v); E.add(u,v); } for(int i=1;i<=n;++i)a[i]=1,tree[i]=lowbit(i); dfs(1); int q; cin>> q; while(q--){ scanf("%s %d",s,&x); if(s[0]=='Q'){ printf("%d\n",sum(out[x])-sum(in[x]-1) ); } else if(s[0]=='C'){ update(in[x] ,1-a[x]*2),a[x]=a[x]^1; } } } return 0; }