【NOI 2015】软件包管理器

【题目链接】

          点击打开链接

【算法】

        树链剖分,子树的DFS序也是连续的一段

        要注意细节!

【代码】

       

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

struct SegmentTree {
    int l,r,sum[2],opt;    
} tree[MAXN*3];

int i,N,Q,x,num;
int depth[MAXN+10],size[MAXN+10],son[MAXN+10],fa[MAXN+10],
    top[MAXN+10],id[MAXN+10];
string type;
vector<int> E[MAXN+10];

template <typename T> inline void read(T &x) {
    int f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; }
    for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
    x *= f;
}

template <typename T> inline void write(T x) {
    if (x < 0) { putchar('-'); x = -x; }
    if (x > 9) write(x/10);
    putchar(x%10+'0');    
}

template <typename T> inline void writeln(T x) {
    write(x);
    puts("");    
}

inline void dfs1(int x) {
    int i,y;
    size[x] = 1;
    for (i = 0; i < E[x].size(); i++) {
        y = E[x][i];
        if (y != fa[x]) {
            fa[y] = x;
            depth[y] = depth[x] + 1;
            dfs1(y);
            size[x] += size[y];
            if ((size[y] > size[son[x]]) || (!son[x])) son[x] = y;
        }
    }    
}

inline void dfs2(int x,int tp) {
    int i,y;
    top[x] = tp; id[x] = ++num;
    if (son[x]) dfs2(son[x],tp);
    for (i = 0; i < E[x].size(); i++) {
        y = E[x][i];
        if ((y != fa[x]) && (y != son[x])) 
            dfs2(y,y);
    }     
}

inline void build(int index,int l,int r) {
    int mid;
    tree[index].l = l; tree[index].r = r;
    tree[index].opt = 0;
    tree[index].sum[0] = r - l + 1;
    if (l == r) return;
    mid = (l + r) >> 1;
    build(index*2,l,mid); build(index*2+1,mid+1,r);    
}

inline void pushdown(int index) {
    if (tree[index].l == tree[index].r) return;
    tree[index*2].opt = tree[index].opt;
    tree[index*2].sum[tree[index].opt] = tree[index*2].r - tree[index*2].l + 1;
    tree[index*2].sum[tree[index].opt^1] = 0;
    tree[index*2+1].opt = tree[index].opt;
    tree[index*2+1].sum[tree[index].opt] = tree[index*2+1].r - tree[index*2+1].l + 1;
    tree[index*2+1].sum[tree[index].opt^1] = 0;    
}

inline void pushup(int index) {
    tree[index].sum[0] = tree[index*2].sum[0] + tree[index*2+1].sum[0];
    tree[index].sum[1] = tree[index*2].sum[1] + tree[index*2+1].sum[1];
    if (tree[index*2].opt != tree[index*2+1].opt) {
        tree[index].opt = -1;
        return;
    }
    if ((tree[index*2].opt == -1) || (tree[index*2+1].opt == -1)) {
        tree[index].opt = -1;
        return;
    }
    tree[index].opt = tree[index*2].opt;
}

void modify(int index,int l,int r,int val) {
    int mid;
    if (tree[index].opt != -1) pushdown(index);
    if ((tree[index].l == l) && (tree[index].r == r)) {
        tree[index].sum[val] = r - l + 1;
        tree[index].sum[val^1] = 0;
        tree[index].opt = val;
    } else {
        mid = (tree[index].l + tree[index].r) >> 1;
        if (mid >= r) modify(index*2,l,r,val);
        else if (mid + 1 <= l) modify(index*2+1,l,r,val);
        else {
            modify(index*2,l,mid,val);
            modify(index*2+1,mid+1,r,val);
        }
        pushup(index);
    }
}

inline int query(int index,int l,int r,int val) {
    int mid;
    if (tree[index].opt != -1) pushdown(index);
    if ((tree[index].l == l) && (tree[index].r == r)) return tree[index].sum[val];
    else {
        mid = (tree[index].l + tree[index].r) >> 1;
        if (mid >= r) return query(index*2,l,r,val);
        else if (mid + 1 <= l) return query(index*2+1,l,r,val);
        else return query(index*2,l,mid,val) + query(index*2+1,mid+1,r,val);
    }
}

inline int Install(int x) {
    int tp = top[x],
        ans = 0;
    while (tp) {
        ans += query(1,id[tp],id[x],0); 
        modify(1,id[tp],id[x],1);
        x = fa[tp]; tp = top[x];
    }    
    ans += query(1,1,id[x],0);
    modify(1,1,id[x],1);
    return ans;
} 

inline int Uninstall(int x) {
     int ans = query(1,id[x],id[x]+size[x]-1,1);    
    modify(1,id[x],id[x]+size[x]-1,0);
    return ans;
}

int main() {
    
    read(N); 
    
    for (i = 1; i < N; i++) {
        read(x);
        E[x].push_back(i);
    }
    
    depth[0] = 1;
    dfs1(0);
    dfs2(0,0);
    
    build(1,1,num);
    
    read(Q);
    while (Q--) {
        cin >> type;
        if (type == "install") {
            read(x);
            writeln(Install(x));
        } else {
            read(x); 
            writeln(Uninstall(x));
        }
    }
    
    return 0;
}
原文地址:https://www.cnblogs.com/evenbao/p/9196437.html