zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    我爱java系列之---【微服务间的认证—Feign拦截器】
    我爱java系列之---【设置权限的三种解决方案】
    581. Shortest Unsorted Continuous Subarray
    129. Sum Root to Leaf Numbers
    513. Find Bottom Left Tree Value
    515. Find Largest Value in Each Tree Row
    155. Min Stack max stack Maxpop O(1) 操作
    painting house
    Minimum Adjustment Cost
    k Sum
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754756.html
Copyright © 2011-2022 走看看