OJ: poj

题目 ID: 3321

标签: dfs序树状数组线段树

日期: 2025-12-03 15:44

目录

标准的带修改求子树和问题

cpp
/**
 * Author by Rainboy blog: https://blog.roj.ac.cn github : https://github.com/rainboylvx
 * date: 2025-12-03 14:59:24
 * oj: poj-3321
 * title: Apple Tree
 * description: dfs-order
 */
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef  long long ll;
const int maxn = 2e6+5;
int n,m;
int a[maxn];
int root = -1;
int apple_status[maxn];

//oisnip_begin邻接表最小实现
/**
 * linklist 的简单实现
 */
// 边结构
struct Edge {
    int to, next;
} e[maxn << 1];

int head[maxn], cnt;

inline void _add(int u,int v) {
    ++cnt;
    e[cnt].to = v;
    e[cnt].next = head[u];
    head[u] = cnt;
}
void add_edge(int u, int v) {
    _add(u, v);
    _add(v,u);
}
//oisnip_end

// dfs-order
int in[maxn],out[maxn];
int dfn_idx;
void dfs_order(int u,int fa) {
    in[u] = ++dfn_idx;

    for(int i = head[u]; i!=-1 ;i = e[i].next)
    {
        int v = e[i].to;
        if(v == fa) continue;
        dfs_order(v,u);
    }
    out[u] = dfn_idx; //最后一个点
}


int tr[maxn*4+5];
typedef int T;
struct sgt_point {
    inline int lp(int p)        { return p<<1;     }
    inline int rp(int p)        { return (p<<1)|1; }
    inline int mid(int l,int r) { return (l+r)>>1; }

    inline void pushup(int p){
        tr[p] = tr[lp(p)] + tr[rp(p)];
    }

    void build(int l,int r,int p){
        if( l == r ) {
            tr[p] = 1; //默认有一个苹果
            // scanf("%d",&tr[p]);
            return;
        }
        int m = mid(l,r);
        build(l,m,lp(p));
        build(m+1,r,rp(p));
        pushup(p);
    }

    void update(int pos,T v,int l,int r,int p){
        if( l == r ) {
            tr[p] += v;
            return;
        }
        int m = mid(l,r);
        if( pos<=m) 
            update(pos,v,l,m,lp(p));
        else 
            update(pos,v,m+1,r,rp(p));
        pushup(p);
    }

    T query(int L,int R,int l,int r,int p){
        if( L <=l && r<=R ) {
            return tr[p];
        }
        int m = mid(l,r);
        T ret = 0;
        if( L <= m ) ret+=query(L,R,l,m,lp(p));
        if( R >=m+1) ret+=query(L,R,m+1,r,rp(p));
        //pushup(p); 因为没有更改,所以不需要
        return ret;
    }
};
sgt_point sgt;


void init(){
    memset(head,-1,sizeof(head));
    std::cin >> n;
    for(int i = 1;i < n ;++i ) // i: 1->n
    {
        int u,v;
        std::cin >> u >> v;
        add_edge(u, v);
    }
    std::cin >> m;
}

signed main (int argc, char *argv[]) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    init();

    dfs_order(1, 0);
    sgt.build(1, n, 1);


    for(int i = 1;i <= m ;++i ) // i: 1->m
    {
        char opt;
        int val;
        std::cin >> opt;
        std::cin >> val;
        if( opt == 'Q') {
            int ans = sgt.query(in[val], out[val], 1,n,1) ;
            std::cout << ans << "\n";
        }
        else {
            sgt.update(in[val], apple_status[val] ? 1 : -1 ,1,n,1);
            apple_status[val] ^= 1; 
        }
    }
    
    return 0;
}