概述
树上计算
Problem:1330
Time Limit:1000ms
Memory Limit:65535K
Description
给出一棵以 1 为根的树,初始每个顶点的权值为 0 。 现有两种操作: 1 x 代表将顶点 x 的权值加一 2 x 询问顶点 x 的子树(包含x本身)的权值和是多少
Input
第一行样例个数 T (T<=10) 对于每组样例 第一行是一个数 N 代表顶点的个数(1 <= N <= 4e4) 随后 N - 1 行每行有两个数 x y 代表顶点 x y 由一条边相连· 接下来一行是一个数 M 代表操作的次数(1<= M <=4e4) 最后 M 行,每行两个数 1 x 或 2 x 代表操作(1 <= x <= N)
Output
每次询问输出答案,每个答案占一行。
Sample Input
10 9 1 2 1 3 2 4 2 5 3 6 6 8 6 7 8 9 9 2 1 1 3 2 6 1 6 1 3 2 1 2 8 1 2 2 1 9 1 2 1 3 2 4 2 5 3 6 3 7 6 8 6 9 5 1 6 2 8 1 3 1 4 2 1
Sample Output
0 0 3 0 4 0 3
Hint
Source
DT2131
中文题。
思路:
先用dfs求出他们的dfs序,ls到rs是他们的子树包括他们自己本身。这样我们就掌握了每个节点他们的子树是什么了。我们只需要一个能单点更新和区间查询的数据结构就行了。树状数组比较好写,我们就用树状数组来完成这件事。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=4e4+500;
int ls[maxn],rs[maxn];
vector<int> v[maxn];
int cnt;
int tr[maxn];
int lowbit(int i)
{
return i&(-i);
}
void update(int i,int n,int c)
{
while(i<=n)
{
tr[i]+=c;
i+=lowbit(i);
}
}
int query(int n)
{
int sum=0;
while(n>0)
{
sum+=tr[n];
n-=lowbit(n);
}
return sum;
}
void dfs(int now,int fa)
{
ls[now]=++cnt;
for(int i=0;i<v[now].size();i++)
{
if(v[now][i]==fa)
continue;
dfs(v[now][i],now);
}
rs[now]=cnt;
}
int main()
{
int t,n,x,y,m,o;
scanf("%d",&t);
while(t--)
{
memset(tr,0,sizeof(tr));
scanf("%d",&n);
cnt=0;
for(int i=1;i<=n;i++)
v[i].clear();
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1,0);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&o,&x);
if(o==1)
{
update(ls[x],n,1);
}
else
{
printf("%dn",query(rs[x])-query(ls[x]-1));
}
}
}
return 0;
}
最后
以上就是美满火车为你收集整理的nefu 1330 树上计算 (dfs序+树状数组)的全部内容,希望文章能够帮你解决nefu 1330 树上计算 (dfs序+树状数组)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复