• 洛谷


    https://www.luogu.org/problem/P2146

    继续重链剖分。
    这里好像很好懂,每次安装软件就区间改值赋值整个路径是1,然后比较前后的sum值变化就可以了。事实上后一次的sum值必定是dep。卸载的话,依赖它的都没了,相当于清空整棵子树。

    #include<bits/stdc++.h>
    #define lc (o<<1)
    #define rc (o<<1|1)
    typedef long long ll;
    using namespace std;
    
    const int MAXN = 100000 + 5;
    int dep[MAXN], siz[MAXN],  son[MAXN], fa[MAXN], top[MAXN], tid[MAXN], rnk[MAXN], cnt;
    
    int n, m, r;
    int head[MAXN], etop;
    
    struct Edge {
        int v, next;
    } e[MAXN * 2];
    
    inline void init(int n) {
        etop = 0;
        memset(head, -1, sizeof(head[0]) * (n + 1));
    }
    
    inline void addedge(int u, int v) {
        e[++etop].v = v;
        e[etop].next = head[u];
        head[u] = etop;
        e[++etop].v = u;
        e[etop].next = head[v];
        head[v] = etop;
    }
    
    struct SegmentTree {
        int sum[MAXN * 4];
        int lz[MAXN * 4];//lz=1,set to 1;lz=-1,set to 0;
    
        void pushup(int o) {
            sum[o] = sum[lc] + sum[rc];
        }
    
        void pushdown(int o, int l, int r) {
            if(lz[o]) {
                lz[lc] = lz[o];
                lz[rc] = lz[o];
                int m = l + r >> 1;
                if(lz[o] == 1) {
                    sum[lc] = (m - l + 1);
                    sum[rc] = (r - m) ;
                } else {
                    sum[lc] = 0;
                    sum[rc] = 0;
                }
                lz[o] = 0;
            }
        }
    
        void update(int o, int l, int r, int ql, int qr, int v) {
            if(ql <= l && r <= qr) {
                lz[o] = v;
                if(v == 1)
                    sum[o] = r - l + 1;
                else
                    sum[o] = 0;
            } else {
                pushdown(o, l, r);
                int m = (l + r) >> 1;
                if(ql <= m)
                    update(lc, l, m, ql, qr, v);
                if(qr >= m + 1)
                    update(rc, m + 1, r, ql, qr, v);
                pushup(o);
            }
        }
    
        int query(int o, int l, int r, int ql, int qr) {
            if(ql <= l && r <= qr) {
                return sum[o];
            } else {
                pushdown(o, l, r);
                int m = (l + r) >> 1;
                int res = 0;
                if(ql <= m)
                    res += query(lc, l, m, ql, qr);
                if(qr >= m + 1)
                    res += query(rc, m + 1, r, ql, qr);
                return res;
            }
        }
    } st;
    
    void init1() {
        dep[r] = 1;
    }
    
    void dfs1(int u, int t) {
        siz[u] = 1, son[u] = -1, fa[u] = t;
        for(int i = head[u]; i != -1; i = e[i].next) {
            int v = e[i].v;
            if(v == t)
                continue;
            dep[v] = dep[u] + 1;
            dfs1(v, u);
            siz[u] += siz[v];
            if(son[u] == -1 || siz[v] > siz[son[u]])
                son[u] = v;
        }
    }
    
    void init2() {
        cnt = 0;
    }
    
    void dfs2(int u, int t) {
        top[u] = t;
        tid[u] = ++cnt;
        rnk[cnt] = u;
        if(son[u] == -1)
            return;
        dfs2(son[u], t);
        for(int i = head[u]; i != -1; i = e[i].next) {
            int v = e[i].v;
            if(v == fa[u] || v == son[u])
                continue;
            dfs2(v, v);
        }
    }
    
    int query1(int u, int v) {
        int ret = 0;
        for(int tu = top[u], tv = top[v]; tu != tv; u = fa[tu], tu = top[u]) {
            if(dep[tu] < dep[tv])
                swap(u, v), swap(tu, tv);
            ret += st.query(1, 1, n, tid[tu], tid[u]);
        }
        if(dep[u] > dep[v])
            swap(u, v);
        ret += st.query(1, 1, n, tid[u], tid[v]);
        return ret;
    }
    
    int query2(int u) {
        return st.query(1, 1, n, tid[u], tid[u]+siz[u]-1);
    }
    
    void update1(int u, int v, int val) {
        for(int tu = top[u], tv = top[v]; tu != tv; u = fa[tu], tu = top[u]) {
            if(dep[tu] < dep[tv])
                swap(u, v), swap(tu, tv);
            st.update(1, 1, n, tid[tu], tid[u], val);
        }
        if(dep[u] > dep[v])
            swap(u, v);
        st.update(1, 1, n, tid[u], tid[v], val);
        return;
    }
    
    void update2(int u, int val) {
        return st.update(1, 1, n, tid[u], tid[u]+siz[u]-1,val);
    }
    
    void install() {
        int x;
        scanf("%d", &x);
        int sum1 = query1(0, x);
        update1(0, x, 1);
        int sum2 = query1(0,x);
        printf("%d
    ", sum2 - sum1);
        return ;
    }
    
    void uninstall() {
        int x;
        scanf("%d", &x);
        int sum1 = query2(x);
        update2(x, -1);
        printf("%d
    ", sum1);
        return;
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        scanf("%d", &n);
        init(n);
        for(int i = 1, u; i <= n - 1; ++i) {
            scanf("%d", &u);
            addedge(i, u);
        }
        r = 0;
        init1();
        dfs1(r, -1);
        init2();
        dfs2(r, r);
        char s[50];
        scanf("%d", &m);
        for(int i = 1; i <= m; ++i) {
            scanf("%s", s);
            switch(s[0]) {
                case 'i':
                    install();
                    break;
                case 'u':
                    uninstall();
                    break;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    SaaS多租户模式数据存储方案比较
    **Apache的Order Allow,Deny 详解
    php使用gd库将文字转换成图片(转)
    [git] warning: LF will be replaced by CRLF | fatal: CRLF would be replaced by LF[ git 处理和修改行结束符(CRLF和LF)]
    解决Linux CentOS中cp -f 复制强制覆盖的命令无效的方法
    【个人专用&入门级】LAMP一键安装包
    【转】负载均衡软件选型
    Apache不重新编译,利用apxs工具给Apache添加模块,如cgi模块
    [Apache手册]Linux环境下配置Apache运行cgi
    phpMyAdmin提示:配置文件权限错误,无法写入!解决方法
  • 原文地址:https://www.cnblogs.com/Yinku/p/11312804.html
Copyright © 2020-2023  润新知