• bzoj4196 [Noi2015]软件包管理器


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4196

    【题解】

    百年不用算法:树链剖分

    刚刚推了一发还是很简单的嘛

    在支持子树修改的同时支持链修改。

    由于子树肯定是在线段树中连在一坨的所以一样修改。

    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 5e5 + 10;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, Q, a[M], par[M];
    int head[M], nxt[M], to[M], tot=0;
    inline void add(int u, int v) {
        ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
    }
    
    int sz[M], mx[M];
    inline void dfs1(int x) {
        int u = 0; sz[x] = 1;
        for (int i=head[x]; i; i=nxt[i]) {
            dfs1(to[i]);
            sz[x] += sz[to[i]];
            if(sz[to[i]] > u) {
                u = sz[to[i]];
                mx[x] = to[i];
            }
        }
    }
    
    int top[M], pos[M], DFN, beg[M], end[M];
    inline void dfs2(int x, int tp) {
        beg[x] = pos[x] = ++DFN; top[x] = tp;
        if(mx[x]) dfs2(mx[x], tp);
        for (int i=head[x]; i; i=nxt[i]) 
            if(to[i] != mx[x]) dfs2(to[i], to[i]);
        end[x] = DFN;    
    }
    
    struct SMT {
        int w[M];
        int tag[M];
        # define ls (x<<1)
        # define rs (x<<1|1)
        inline void up(int x) {
            if(!x) return ;
            w[x] = w[ls] + w[rs];
        }
        inline void pushtag(int x, int l, int r, int d) {
            if(!x) return ;
            w[x] = d*(r-l+1);
            tag[x] = d;
        }
        inline void down(int x, int l, int r) {
            if(!x) return ;
            if(tag[x] == -1) return ;
            int mid = l+r>>1;
            pushtag(ls, l, mid, tag[x]);
            pushtag(rs, mid+1, r, tag[x]);
            tag[x] = -1;
        }
        inline void edt(int x, int l, int r, int L, int R, int d) {
            if(L <= l && r <= R) {
                pushtag(x, l, r, d);
                return ;
            }
            down(x, l, r);
            int mid = l+r>>1;
            if(L <= mid) edt(ls, l, mid, L, R, d);
            if(R > mid) edt(rs, mid+1, r, L, R, d);    
            up(x);
        }
        inline int query(int x, int l, int r, int L, int R, int d) {
            if(L <= l && r <= R) {
                if(d == 1) return w[x];
                else return r-l+1-w[x];
            }
            down(x, l, r);
            int mid = l+r>>1, ret = 0;
            if(L <= mid) ret += query(ls, l, mid, L, R, d);
            if(R > mid) ret += query(rs, mid+1, r, L, R, d);
            return ret;
        }
    }T;
    
    
    
    int main() {
        cin >> n;
        for (int i=2; i<=n; ++i) {
            scanf("%d", par+i); ++par[i];
            add(par[i], i);
        }
        dfs1(1);
        dfs2(1, 1);
    //    for (int i=1; i<=n; ++i) printf("x = %d, top = %d, pos = %d
    ", i, top[i], pos[i]);
        for (int i=1; i<=n*4; ++i) T.w[i] = 0, T.tag[i] = -1;
        cin >> Q;
        char str[23]; int x;
        while(Q--) {
            scanf("%s%d", str, &x); ++x;
            if(str[0] == 'i') {
                // install
                int t = x, tp, ans = 0;
                while(1) {
                    tp = top[t];
                    ans += T.query(1, 1, n, pos[tp], pos[t], 0);
                    if(tp == 1) break;
                    t = par[tp];
                }
                printf("%d
    ", ans);
                t = x;
                while(1) {
                    tp = top[t];
                    T.edt(1, 1, n, pos[tp], pos[t], 1);
                    if(tp == 1) break;
                    t = par[tp];
                }
            } else {
                // uninstall
    //            printf("%d %d
    ", beg[x], end[x]);
                printf("%d
    ", T.query(1, 1, n, beg[x], end[x], 1));
                T.edt(1, 1, n, beg[x], end[x], 0);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    *三维数组的初始化及遍历三个for循环
    *二维数组的初始化
    用while判读循环语句1+1/2!+1/3!+...1/20!的和阶乘的计算方法 式:n!=n*(n-1)!
    求一组数组各个元素的和*
    *求一组数组各个元素的和*
    使用for循环输出杨辉三角-还是不懂得需要复习
    使用for循环输出空心的菱形的思路-还是没有办法理解
    Break用法再举例
    continue用来结束本次循环 break用来结束整个循环体
    LeetCode.1154-一年中的第几天(Day of the Year)
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj4196.html
Copyright © 2020-2023  润新知