题目链接:
http://poj.org/problem?id=3321
题意:
给你一颗n个节点的树,每个节点开始有一个苹果,然后m次修改,每次修改使得某个节点的苹果改变,有变成没有,没有变成有。询问的是某个节点及其子树的苹果数目。
题解:
dfs序之后,单点修改区间查询,线段树与树状数组都可以。
普通的vector在这道题中迷之超时,加了个 typedef 后就不超时了,真是神奇,手写边表的话应该没什么问题。
代码:
#include
#include
#include
#include
#include
#define lson (id*2)
#define rson (id*2+1)
#define maxn (100005)
using namespace std;
int n,in[maxn],out[maxn],m,tot;
//神奇的定义方法
typedef vector<int> ve_int;
vector lin(100005);
void dfs(int x,int f)
{
tot++;
in[x]=tot;
for (int i=0;iif (lin[x][i]!=f)
dfs(lin[x][i],x);
out[x]=tot;
}
char p[3];
int tr[4*maxn];
void pushup(int id)
{
tr[id]=tr[lson]+tr[rson];
}
void build(int id,int l,int r)
{
if (l>r) return ;
if (l==r)
{
tr[id]=1;
return ;
}
int mid=(l+r)/2;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(id);
}
void exc(int id,int l,int r,int x)
{
if (l>r) return ;
if (l==r&&r==x)
{
if (tr[id]==1) tr[id]=0;
else tr[id]=1;
return ;
}
int mid=(l+r)/2;
if (x<=mid) exc(lson,l,mid,x);
if (x>=mid+1) exc(rson,mid+1,r,x);
pushup(id);
}
int ans;
void query(int id,int l,int r,int L,int R)
{
if (l>r || L>r || Rreturn ;
if (l>=L && r<=R)
{
ans+=tr[id];
return ;
}
int mid=(l+r)/2;
if (L<=mid) query(lson,l,mid,L,R);
if (R>=mid+1) query(rson,mid+1,r,L,R);
pushup(id);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n-1;i++)
{
int tmpa,tmpb;
scanf("%d%d",&tmpa,&tmpb);
lin[tmpa].push_back(tmpb);
lin[tmpb].push_back(tmpa);
}
dfs(1,1);
build(1,1,tot);
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
int tmp;
scanf("%s",p);
scanf("%d",&tmp);
if (p[0]=='Q')
{
ans=0;
//cout<
query(1,1,tot,in[tmp],out[tmp]);
printf("%d\n",ans);
}
else
exc(1,1,tot,in[tmp]);
}
}