給出乙個 n 個節點的樹,對於每個節點上一開始都有乙個蘋果,有 m 個操作,有 c x,q x 兩個操作,c x表示把 x 號節點如果有蘋果就拿掉,否則就放上乙個,q x 表示查詢 x 為根的子樹的蘋果當前有幾個(n, m <= 100000)
只是對於所有樹上的節點,我們用 dfs 時間戳 (dfs 序) 來對映成一段連續的,然後對於乙個節點的子樹對應的區間就是 d[x], d[x] + size[x] - 1,然後直接查詢修改即可
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
#define begin begin
#define next next
#define rep(i, a, b) for (int i = (a), _end_ = (b); i <= _end_; ++i)
#define erep(i, a) for (int i = begin[a]; i > 0; i = next[i])
#define debug(...) fprintf(stderr, __va_args__)
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define sz(x) (int((x).size()))
#define all(x) (x).begin(), (x).end()
template
inline
bool chkmin(t &a, const t &b)
template
inline
bool chkmax(t &a, const t &b)
typedef
long
long ll;
const
int dmax = 100100
<< 2, oo = 0x3f3f3f3f;
int n, m;
int begin[dmax], to[dmax], next[dmax], e;
int d[dmax], size[dmax], dis;
int c[dmax];
inline
void init()
inline
void add(int x, int y)
void dfs(int x, int fa)
}#define left x << 1, l, mid
#define right x << 1 | 1, mid + 1, r
template
inline t mid(const t &x, const t &y)
inline
void push_up(int x)
void create(int x, int l, int r)
int mid = mid(l, r);
create(left);
create(right);
push_up(x);
}int query(int x, int l, int r, int s, int t)
void update(int x, int l, int r, int t)
int mid = mid(l, r);
if (t <= mid)
update(left, t);
else update(right, t);
push_up(x);
}int main()
dfs(1, 0);
create(1, 1, n);
scanf("%d", &m);
getchar();
rep(i, 1, m)
}return
0;}
POJ3321 樹狀陣列或線段樹,對映
這個題並不是常規的樹狀陣列或線段樹的題,因為他本身給你的並不是乙個線性的序列,而是一棵樹。如果單純的用dfs不斷遍歷更新,n 100000時間上受不了,又得考慮樹狀陣列或線段樹來做這種題。思路是,對每個樹上的點,標記乙個dfs時間戳,lef index 表示dfs從點index開始的時間戳,而rig...
POJ 3321 樹狀陣列
題意 給定一棵樹,某些節點上有蘋果,多次詢問各子樹上的節點數,並且在詢問的中途隨時可能新增和刪除蘋果。分析 dfs遍歷樹的同時,對每個點標註時間,每個點有乙個開始時間和乙個結束時間,把這兩個時間當做下標,該點的蘋果個數 1或0 填入陣列的兩個對應位。子樹中結點的時間段一定是根節點時間段的子段,所以求...
poj 3321 樹狀陣列
首先對數進行dfs一下,前序優先遍歷,這樣做的目的是令節點i的子節點的編號組成的集合是一段連續的數,這樣在查詢的時候就能夠用樹狀陣列來查詢連續的區間的和 ac 如下 include include include include using namespace std const int max n...