【poj】 3321 Apple Tree dfs序+树状数组

来源:互联网 发布:东京食尸鬼面具淘宝 编辑:程序博客网 时间:2024/06/05 22:37

链接

题目大意:…蒟蒻英语语文都不好…codevs上有中文翻译qwq 上链接

这个题是dfs序的应用中初心者的题目。暑假学长就让我们做,然而当时我还不会什么树状数组,线段树也懒得打。这几天敲了几次树状数组的模板,就赶紧来填这个坑了。

dfs序据说是处理子树问题的神器。dfs序的性质就是一棵子树内的所有节点在序列中都是连续的(比如以u为根的子树,都在in[u]和out[u]之间)。我们在dfs过程中记录一下这两个时间戳,分别代表进入这个节点的时间戳和离开这个节点的时间戳。这样在树上的问题就可以转化成了区间问题。对于区间问题就可以用线段树或树状数组来很好的求解啦。

这里有个写的比较好的博文你们可以看下qwq链接

对于这个题来说,用dfs序把树上问题转化为区间问题以后,用树状数组维护单点修改和区间和就可以了(用线段树练习一的模板就可以了)

代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define lowbit(x) (x&-x)#define SZ 200000+10using namespace std;int first[SZ],nxt[SZ<<1],in[SZ],out[SZ];int tree[SZ];int n,tot=0,tim=0;struct edge{    int from,to,cost;}es[SZ<<1];bool vis[SZ],use[SZ];char s[10];void build(int ff,int tt){    es[++tot]=(edge){ff,tt};    nxt[tot]=first[ff];    first[ff]=tot;}void dfs(int u){    vis[u]=1;    in[u]=++tim;    for(int i=first[u];i!=-1;i=nxt[i])    {        int v=es[i].to;        if(!vis[v])            dfs(v);    }    out[u]=++tim;}void add(int x,int y){    while(x<=tim)    {        tree[x]+=y;        x+=lowbit(x);    }}int sum(int x){    int ans=0;    while(x)    {        ans+=tree[x];        x-=lowbit(x);    }    return ans;}int ask(int x,int y){    return sum(y)-sum(x-1);}int main(){    memset(first,-1,sizeof(first));    scanf("%d",&n);    for(int i=1;i<n;i++)    {        int ff,tt;        scanf("%d%d",&ff,&tt);        build(ff,tt);        build(tt,ff);    }    dfs(1);    for(int i=1;i<=n;i++)        add(in[i],1);    int m;    scanf("%d",&m);    while(m--)    {        int a;        scanf("%s",&s);        if(s[0]=='C')        {            scanf("%d",&a);            if(!use[a])            {                use[a]=1;                add(in[a],-1);            }            else            {                use[a]=0;                add(in[a],1);            }        }        else        {            scanf("%d",&a);            printf("%d\n",ask(in[a],out[a]));        }    }    return 0;}
1 0
原创粉丝点击