poj3321(dfs序+线段树)

  题意就是给一棵树,然后有2种操作,一是问以x为根节点的子树有多少苹果,二是更改某点的苹果数量。

 做法就是用dfs序把树形结构转化成线性结构也就是区间,然后用线段树维护。先要求出每个点的in和out值,然后就给每个点分配了一个新编号了,就是它的in[i],然后dfs序有个特点就是以x为根节点的子树里的节点的dfs序是连续的,所以in[x]~out[x]就对应着这颗子树的信息,查询的话对in[x]~out[x]区间操作。

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define ls rt<<1
#define rs (rt<<1)|1
#define fuck(x) cout<<#x<<"     "<<x<<endl;
const int maxn=1e5+10;
struct node
{
    int u,v,nxt;
}e[maxn<<1];
int head[maxn],in[maxn],out[maxn],order[maxn],sum[maxn<<2],tim;
void pushup(int rt)
{
    sum[rt]=sum[ls]+sum[rs];
}
void build(int rt,int L,int R)
{
    if(L==R)
    {
        sum[rt]=1;
        return ;
    }
    int mid=(L+R)>>1;
    build(ls,L,mid);
    build(rs,mid+1,R);
    pushup(rt);
}
void update(int rt,int L,int R,int pos)
{
    if(L==R)
    {
        if(sum[rt])
            sum[rt]=0;
        else
            sum[rt]=1;
        return ;
    }
    int mid=(L+R)>>1;
    if(pos<=mid)
        update(ls,L,mid,pos);
    else
        update(rs,mid+1,R,pos);
    pushup(rt);
}
int query(int rt,int L,int R,int l,int r)
{
    if(l<=L&&r>=R)
    {
        return sum[rt];
    }
    int mid=(L+R)>>1,ans=0;
    if(r<=mid)
        ans=query(ls,L,mid,l,r);
    else
        if(l>mid)
            ans=query(rs,mid+1,R,l,r);
        else
            ans=query(ls,L,mid,l,r)+query(rs,mid+1,R,l,r);
    return ans;
}
void dfs(int now,int fa)
{
    in[now]=++tim;
    for(int i=head[now];i!=-1;i=e[i].nxt)
    {
        if(e[i].v==fa) continue;
        dfs(e[i].v,now);
    }
    out[now]=tim;
}

int main()
{
    int n,q,cnt=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) head[i]=-1;
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        e[++cnt].u=u;
        e[cnt].v=v;
        e[cnt].nxt=head[u];
        head[u]=cnt;
        e[++cnt].u=v;
        e[cnt].v=u;
        e[cnt].nxt=head[v];
        head[v]=cnt;
    }
    dfs(1,0);
    for(int i=1;i<=n;i++) order[in[i]]=i;
    build(1,1,n);
    scanf("%d",&q);
    while(q--)
    {
        char ch;
        int k;
        scanf(" %c%d",&ch,&k);
        if(ch=='C')
            update(1,1,n,in[k]);
        else
            printf("%d
",query(1,1,n,in[k],out[k]));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/eason9906/p/11754756.html