树链剖分 - AcWing 918 - 软件包管理器

树链剖分 - AcWing 918 - 软件包管理器

这道题也挺板的,线段树的lazy维护区间置数即可。

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5+5, M = N<<2;

int n, m;
int a, b, x;
char op[20];

// seg
int tree[N<<2];
int lazy[N<<2];

void push_up(int rt){
    tree[rt] = tree[rt<<1] + tree[rt<<1|1];
}

void push_down(int rt, int l, int r){
    if(lazy[rt] != -1){
        int mid = l+r>>1;
        tree[rt<<1] = (mid-l+1) * lazy[rt];
        tree[rt<<1|1] = (r-mid) * lazy[rt];
        lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
        lazy[rt] = -1;
    }
}


void modify(int rt, int l, int r,int ml, int mr, int v){
    if(ml <= l && mr >= r){
        tree[rt] = (r-l+1)*v;
        lazy[rt] = v;
    }else{
        push_down(rt, l, r);
        int mid = l+r>>1;
        if(ml <= mid){
            modify(rt<<1, l, mid, ml, mr, v);
        }
        if(mr > mid){
            modify(rt<<1|1, mid+1, r, ml, mr, v);
        }
        push_up(rt);
    }
}

int query(int rt, int l, int r, int ql, int qr){
    if(ql <= l && qr >= r){
        return tree[rt];
    }else{
        push_down(rt, l, r);
        int ans = 0;
        int mid = l+r>>1;
        if(ql <= mid){
            ans += query(rt<<1, l, mid, ql, qr);
        }
        if(qr > mid){
            ans += query(rt<<1|1, mid+1, r, ql, qr);
        }
        return ans;
    }
}


// lct
vector<int> edges[N];
int fa[N];
int head[N];
int dep[N];
int heavy_son[N];
int dfs_id[N];
int subtree_begin[N];
int subtree_end[N];


int dfs1(int cur, int depth){
    dep[cur] = depth;
    int tot_size = 1, cur_size = 0,max_size = 0, max_root = 0;
    for(auto it = edges[cur].begin(); it != edges[cur].end(); ++it){
        cur_size = dfs1(*it, depth+1);
        tot_size += cur_size;
        if(cur_size > max_size){
            max_size = cur_size;
            max_root = *it;
        }
    }
    heavy_son[cur] = max_root;
    return tot_size;
}

void dfs2(int cur, int head_node, int& id){
    head[cur] = head_node;
    dfs_id[cur] = id++;
    if(heavy_son[cur]){
        dfs2(heavy_son[cur], head_node, id);
    }
    for(auto it = edges[cur].begin(); it != edges[cur].end(); ++it){
        if(*it == heavy_son[cur]) continue;
        dfs2(*it, *it, id);
    }
    subtree_begin[cur] = dfs_id[cur];
    subtree_end[cur] = id-1;
}

void build_lct(){
    int id = 1;
    dfs1(1, 1);
    dfs2(1, 1, id);
}

void modify_lct(int a, int b,int v){
    int ha, hb;
    while(1){
        ha = head[a];
        hb = head[b];
        if(ha == hb){
            a = dfs_id[a];
            b = dfs_id[b];
            if(a > b) swap(a, b);
            modify(1, 1, n, a, b, v);
            break;
        }else{
            if(dep[ha] < dep[hb]){
                swap(a, b);
                swap(ha, hb);
            }
            modify(1, 1, n, dfs_id[ha], dfs_id[a], v);
            a = fa[ha];
        }
    }
}


int query_lct(int a, int b){
    int ans = 0;
    int ha, hb;
    while(1){
        ha = head[a];
        hb = head[b];
        if(ha == hb){
            a = dfs_id[a];
            b = dfs_id[b];
            if(a > b) swap(a, b);
            ans += query(1, 1, n, a, b);
            break;
        }else{
            if(dep[ha] < dep[hb]){
                swap(a, b);
                swap(ha, hb);
            }
            ans += query(1, 1, n, dfs_id[ha], dfs_id[a]);
            a = fa[ha];
        }
    }
    return ans;
}


int main(){
    scanf("%d", &n);
    for(int i = 2; i <= n; ++i){
        scanf("%d",&a);
        ++a;
        edges[a].push_back(i);
        fa[i] = a;
    }
    build_lct();
    
    for(int i = 0; i < M; ++i){
        lazy[i] = -1;
    }


    scanf("%d", &m);
    while(m--){
        scanf("%s%d", op, &x);
        ++x;
        if(*op == 'i'){
            printf("%d\n", dep[x] - query_lct(1, x));
            modify_lct(1, x, 1);
        }else{
            printf("%d\n", query(1, 1, n, subtree_begin[x], subtree_end[x]));
            modify(1, 1, n, subtree_begin[x], subtree_end[x], 0);
        }
    }
    return 0;
}

posted @ 2021-03-02 12:01  popozyl  阅读(40)  评论(0编辑  收藏  举报