您的位置:首页 > 其它

POJ3321 线段树水题

2016-05-29 23:25 337 查看

题目大意

给出一个 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>

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<typename T> inline bool chkmin(T &a, const T &b){ return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b){ return a < b ? a = b, 1 : 0; }

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()
{
e = dis = 0;
memset(begin, 0, sizeof begin);
}

inline void add(int x, int y)
{
to[++e] = y;
next[e] = begin[x];
begin[x] = e;
}

void dfs(int x, int fa)
{
size[x] = 1;
d[x] = ++dis;
EREP(i, x)
if (to[i] != fa)
{
dfs(to[i], x);
size[x] += size[to[i]];
}
}

#define left x << 1, l, mid
#define right x << 1 | 1, mid + 1, r

template<typename T> inline T Mid(const T &x, const T &y){ return (x + y) >> 1; }

inline void push_up(int x){ c[x] = c[x << 1] + c[x << 1 | 1]; }

void create(int x, int l, int r)
{
if (l == r)
{
c[x] = 1;
return;
}
int mid = Mid(l, r);
create(left);
create(right);
push_up(x);
}

int query(int x, int l, int r, int s, int t)
{
if (l >= s && r <= t)
return c[x];
int mid = Mid(l, r);
int sum = 0;
if (s <= mid)
sum += query(left, s, t);
if (t > mid)
sum += query(right, s, t);
return sum;
}

void update(int x, int l, int r, int t)
{
if (l == r)
{
c[x] ^= 1;
return;
}
int mid = Mid(l, r);
if (t <= mid)
update(left, t);
else update(right, t);
push_up(x);
}

int main()
{
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
while (scanf("%d", &n) != EOF)
{
init();
REP(i, 1, n - 1)
{
int x, y;
scanf("%d%d", &x, &y);
add(x, y);
add(y, x);
}
dfs(1, 0);
create(1, 1, n);
scanf("%d", &m);
getchar();
REP(i, 1, m){
char c = getchar();
int x;
scanf("%d", &x);
if (c == 'Q')
printf("%d\n", query(1, 1, n, d[x], d[x] + size[x] - 1));
else update(1, 1, n, d[x]);
getchar();
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: