题目大意,就是给出一棵树,可能有很多叉,然后每个叉上长一个苹果,有两种操作,第一种是C ,意思就是change,如果这个叉上有苹果,就摘掉,如果没有,就长一个。
另一种操作是Q,意思就是询问,问的是某个结点及其子树上的苹果有多少个。
这是很明显的区间求和问题,用树状数组来很方便,关键是这个是树形的结构,所以必须先把树映射出来,也就是相当于把数据离散化了,这里就要先进行一次DFS了,开两个数组,low和high,low代表的就是结点进入的时间,实际上也是结点映射出的编号,high就是离开的时间,那么这个结点的子树就是low和high之间的所有叉了。
/*
ID: sdj22251
PROG: subset
LANG: C++
*/
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define MAXN 222222
#define MAXM 104444
#define INF 100000000
#define PI acos(-1.0)
#define eps 1e-12
#define L(X) X<<1
#define R(X) X<<1|1
using namespace std;
struct node
{
int v, next;
}edge[2 * MAXN];
int head[MAXN], e, cnt, n, m;
int low[MAXN], high[MAXN], vis[MAXN], a[MAXN];
void insert(int x, int y)
{
edge[e].v = y;
edge[e].next = head[x];
head[x] = e++;
edge[e].v = x;
edge[e].next = head[y];
head[y] = e++;
}
void init()
{
e = cnt = 0;
memset(head, -1, sizeof(head));
}
void dfs(int u)
{
low[u] = ++cnt;
vis[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next)
if(!vis[edge[i].v]) dfs(edge[i].v);
high[u] = cnt;
}
int lowbit(int x)
{
return x & -x;
}
void modify(int x, int v)
{
for(int i = x; i <= n; i += lowbit(i))
a[i] += v;
}
int get_sum(int x)
{
int sum = 0;
for(int i = x; i >= 1; i -= lowbit(i))
sum += a[i];
return sum;
}
int main()
{
init();
scanf("%d", &n);
int x, y;
char op[5];
for(int i = 0; i < n - 1; i++)
{
scanf("%d%d", &x, &y);
insert(x, y);
}
dfs(1);
scanf("%d", &m);
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++)
modify(i, 1);
for(int i = 0; i < m; i++)
{
scanf("%s%d", op, &x);
if(op[0] == 'C')
{
if(vis[x]) modify(low[x], 1);
else modify(low[x], -1);
vis[x] = (!vis[x]);
}
else
{
int ans = get_sum(high[x]) - get_sum(low[x] - 1);
printf("%d\n", ans);
}
}
return 0;
}
分享到:
相关推荐
这是一道很不错的题目,即可以用线段树做也可以用树状数组,可谓经典。不过当然了线段树是比较难搞,而树状数组是极其简洁的,构造很简单,下面就分别来介绍一下两种方法...
NULL 博文链接:https://128kj.iteye.com/blog/1745671
NULL 博文链接:https://128kj.iteye.com/blog/1744222
NULL 博文链接:https://128kj.iteye.com/blog/1744555
NULL 博文链接:https://128kj.iteye.com/blog/1747400
北大POJ2255-Tree Recovery 解题报告+AC代码
poj 2201 Cartesian Tree.md
NULL 博文链接:https://128kj.iteye.com/blog/1746750
Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist(u,v)=The min distance between node u and v. Give an integer k,for every pair (u,v) of vertices is ...
Poj 3342 这是一道树状dp题目,题意是这样的,一个公司,每个人有且仅有一个Boss,除了最大的Boss没有Boss(显然),现在要参加一个聚会,要求参加的人数最多,但是棘手的.......
工大的poj答案,大一的盆友都懂哒
POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类
poj上第1990题目源码,用到了2个树状数组,这题数据结构是关键,想到了题目就很简单了
北大POJ2525-Text Formalization【TrieTree】 解题报告+AC代码+测试数据 http://hi.csdn.net/!s/XW4FQ3
西工大POJ习题第五季,数组这类的代码,有截图
原理为:以数链思想,移动数组中的内容 使数组在没有扩充情况下,达成移动的效果 当然,有更简单的,大牛不要笑哦
poj 1909 Marbles on a tree.md
建树,树的遍历访问,联系数据结构不错的题目
NULL 博文链接:https://128kj.iteye.com/blog/1757060
poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题...