Apple Tree POJ - 3321(线段树+dfs序)

版权声明:欢迎大家指正错误,有不同观点的欢迎评论,共同进步 https://blog.csdn.net/Sirius_han/article/details/82705504

Apple Tree POJ - 3321

题目连接

题意:一棵苹果树,初始每个节点上都有一个苹果,共n个节点,m个操作,分两种:
Q x:x节点的子树中共有多少个苹果;
C x:若x节点处有苹果,就摘掉,反之就长出苹果;
思路:根据树的dfs序将树转换线性问题,再利用线段树求解;

#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn=1e5+10;
struct Edge{
    int v, nxt;
    Edge(){}
    Edge(int v0, int n){
        v=v0, nxt=n;
    }
}edge[maxn<<1];
int head[maxn], cnt;
void add(int u, int v){
    edge[cnt]=Edge(v, head[u]);
    head[u]=cnt++;
}
int l[maxn], r[maxn], num;//l[x],r[x]分别表示树上的结点x的子树的左右区间;
void dfs(int u, int fa){
    l[u]=++num;
    for(int i=head[u]; i!=-1; i=edge[i].nxt){
        int v=edge[i].v;
        if(v==fa) continue;
        dfs(v, u);
    }
    r[u]=num;
}
struct node{
    int l, r, sum;
}tr[maxn<<2];
void pushup(int m){
    tr[m].sum=tr[m<<1].sum+tr[m<<1|1].sum;
}
void build(int m, int l, int r){
    tr[m].l=l;
    tr[m].r=r;
    if(l==r){
        tr[m].sum=1;
        return;
    }
    int mid=(l+r)>>1;
    build(m<<1, l, mid);
    build(m<<1|1, mid+1, r);
    pushup(m);
}
void updata(int m, int inx){
    if(tr[m].l==tr[m].r){
        tr[m].sum=(tr[m].sum+1)%2;
        return;
    }
    int mid=(tr[m].l+tr[m].r)>>1;
    if(inx<=mid) updata(m<<1, inx);
    else updata(m<<1|1, inx);
    pushup(m);
}
int query(int m, int l, int r){
    if(tr[m].l==l&&tr[m].r==r){
        return tr[m].sum;
    }
    int mid=(tr[m].l+tr[m].r)>>1;
    if(r<=mid) return query(m<<1, l, r);
    else if(l>mid) return query(m<<1|1, l, r);
    else return query(m<<1, l, mid)+query(m<<1|1, mid+1, r);
}
int main(){
    int n, m;
    while(~scanf("%d", &n)){
        memset(head, -1, sizeof(head));
        cnt=0;
        for(int i=1; i<n; i++){
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v);
            add(v, u);
        }
        num=0;
        dfs(1, 1);
        build(1, 1, num);
        scanf("%d", &m);
        while(m--){
            char op[5];
            int x;
            scanf("%s%d", op, &x);
            if(op[0]=='Q'){
                printf("%d\n", query(1, l[x], r[x]));
            }
            else{
                updata(1, l[x]);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Sirius_han/article/details/82705504