题目链接:http://poj.org/problem?id=3321
树状数组裸题,对于每个时间点,设置两个时间戳,分别记录dfs时的进栈时间和出栈时间,前缀和做差就是子数中被标记的个数
贴代码
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100005;
int c[maxn],inn[maxn],oun[maxn],link[maxn],son[2*maxn],next[2*maxn],n,tot,len,m;
bool vis[maxn];
int lowbit(int x){
return x & -x;
}
void add(int x,int y){
while (x<=n){
c[x]+=y;
x+=lowbit(x);
}
}
int query(int x){
int s=0;
while (x>=1){
s+=c[x];
x-=lowbit(x);
}
return s;
}
void add1(int x,int y){
tot++;son[tot]=y;next[tot]=link[x];link[x]=tot;
}
void dfs(int x){
vis[x]=true;
len++;
inn[x]=len;
int j=link[x];
while (j!=0){
if (!vis[son[j]]) dfs(son[j]);
j=next[j];
}
oun[x]=len;
}
int main(){
//freopen("apple.in","r",stdin);
//freopen("apple.out","w",stdout);
memset(link,sizeof(link),0);
tot=0;
scanf("%d\n",&n);
for (int i=1;i<n;i++){
int x,y;
scanf("%d%d\n",&x,&y);
add1(x,y);add1(y,x);
}
len=0;
dfs(1);
for (int i=1;i<=n;i++) add(i,1);
c[0]=0;
memset(vis,sizeof(vis),true);
scanf("%d\n",&m);
for (int i=1;i<=m;i++){
int x;
char ch;
scanf("%c%d\n",&ch,&x);
if (ch=='Q') printf("%d\n",query(oun[x])-query(inn[x]-1));
else {
if (vis[x]) add(inn[x],-1);
else add(inn[x],1);
vis[x]=!vis[x];
}
}
return 0;
}
【写的有漏洞的,欢迎路过大神吐槽】
2016/11/14 11:44:06
Ending.