您的位置:首页 > 其它

poj 3321/3263 树状数组(苹果树/排身高)

2015-07-22 21:40 183 查看
题意:每个分叉点及末梢可能有苹果(最多1个), 每次可以摘掉一个苹果,或有一个苹果新长出来,随时查询某个分叉点所在的子树里, 一共有多少个苹果。

思路:深度优先遍历整个苹果树,为每个节点标记一个开始时间和结束时间(所有时间都不相同),显然子树里面所有节点的开始和结束时间,都位于子树树根的开始和结束时间之间。那么苹果的有无只需在开始时间那个点(在结束时间那个点上也可以)上面进行加减1的操作即可。然后每次查询就看看从开始点到结束点之间的和一共是多少。用线段树或者树状数组皆可。树状数组容易写,遂用之。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define N 100005
#define INF 0x3fffffff
using namespace std;
#define N 100005
int tree[N<<1];
struct edge{
int y,next;
}e[N<<1];
int first
,top,n,q,len;
int s
,w
,flag
;
void add(int x,int y){
e[top].y = y;
e[top].next = first[x];
first[x] = top++;
}
void dfs(int x){//对树进行dfs,得到起始和终止的时间戳
int i;
s[x] = ++len;
for(i = first[x];i!=-1;i=e[i].next)
if(!s[e[i].y])
dfs(e[i].y);
w[x] = ++len;
}
int lowbit(int x){
return x&(-x);
}
void addtree(int i,int x){
for(int j = i;j<=2*n;j+=lowbit(j))
tree[j] += x;
}
int sum(int x){
int i,res = 0;
for(i = x;i>=1;i-=lowbit(i))
res += tree[i];
return res;
}
int main(){
int i,a,b,x;
char ch;
scanf("%d",&n);
memset(s,0,sizeof(s));
memset(first,-1,sizeof(first));
top = len = 0;
for(i = 1;i<n;i++){
scanf("%d %d",&a,&b);
add(a,b);
add(b,a);
}
dfs(1);
for(i = 1;i<=n;i++){
flag[i] = 1;
addtree(s[i],1);//初始所有fork上都有苹果
}
scanf("%d",&q);
while(q--){
getchar();
ch = getchar();
scanf("%d",&x);
if(ch == 'Q')
printf("%d\n",sum(w[x])-sum(s[x]-1));
else{
if(flag[x])//有变成没有,那么在相应时间戳上去掉这个苹果即可
addtree(s[x], -1);
else
addtree(s[x], 1);
flag[x] = 1-flag[x];
}
}
return 0;
}


poj3263:计数的思路如出一辙。需要注意的是a看到b和b看到a是一个意思,不能重复计数,所以要筛一遍。另外题目给的最高高度的索引是没有用的。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstdlib>
using namespace std;
#define clc(s,t) memset(s,t,sizeof(s))
#define INF 0x3fffffff
#define N 10005
struct node{
int a,b;
}s
;
int tree
;
int n,m,h,t;
int cmp(node x,node y){
if(x.a == y.a)
return x.b<y.b;
return x.a<y.a;
}
int lowbit(int x){
return x&(-x);
}
void add(int i,int x){
for(int j = i;j<=n;j+=lowbit(j))
tree[j] += x;
}
int sum(int i){
int j,res=0;
for(j = i;j>=1;j-=lowbit(j))
res += tree[j];
return res;
}
int main(){
int i,j,x,y;
scanf("%d %d %d %d",&n,&t,&h,&m);
for(i = 0;i<m;i++){
scanf("%d %d",&s[i].a,&s[i].b);
if(s[i].a > s[i].b)
swap(s[i].a,s[i].b);
}
sort(s,s+m,cmp);
for(i = 0;i<m;i++){
if(i && s[i].a==s[i-1].a && s[i].b==s[i-1].b)//去掉重复的
continue;
add(s[i].a+1,-1);
add(s[i].b,1);
}
for(i = 1;i<=n;i++)
printf("%d\n",h+sum(i));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: