zoukankan      html  css  js  c++  java
  • 树链剖分

    树链剖分 - 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
    ", dep[x] - query_lct(1, x));
                modify_lct(1, x, 1);
            }else{
                printf("%d
    ", query(1, 1, n, subtree_begin[x], subtree_end[x]));
                modify(1, 1, n, subtree_begin[x], subtree_end[x], 0);
            }
        }
        return 0;
    }
    
    
    ---- suffer now and live the rest of your life as a champion ----
  • 相关阅读:
    springboot mail+Thymeleaf模板
    jax-rs示例
    java enum的一种写法记录
    lintcode 最大子数组III
    lintcode 单词接龙II
    idea springboot热部署无效问题
    java8 Optional正确使用姿势
    Spring根据包名获取包路径下的所有类
    无状态shiro认证组件(禁用默认session)
    获取资源文件工具类
  • 原文地址:https://www.cnblogs.com/popodynasty/p/14468248.html
Copyright © 2011-2022 走看看